Visual Studio podczas debugowania: ocena funkcji wymaga uruchomienia wszystkich wątków

93

Nagle pojawia się dziwny błąd podczas debugowania. Do tej pory zmienna w oknach obserwacyjnych była wyświetlana poprawnie. Teraz w oknach zegarka zawsze pojawia się komunikat o błędzie:

Ocena funkcji wymaga działania wszystkich wątków

Nie mogę już sprawdzić żadnej zmiennej. Nie jestem jawny w pracy z wątkami. Co mogę zrobić, aby znów działał?

Wyłączyłem już, jak wspomniano na niektórych forach, funkcję: "Włącz ocenę właściwości i inne niejawne wywołania funkcji" w oknie opcji debuggera. Ale bez powodzenia otrzymuję błąd:

Niejawna ocena funkcji błędu wyłączona przez użytkownika

Maik
źródło
Aby uzyskać ten punkt na liście: Czy program Visual Studio został ponownie uruchomiony?
MUG4N
Tak. Zrestartowany i ten sam problem.
Maik
Nawet gdyby to zadziałało, to nie może być rozwiązaniem, ponieważ chcę korzystać z platformy NET 4.x Framework. Nie chcę obniżać wersji tylko dlatego, że to problem. Zastanawiam się, dlaczego jakiś czas temu to działało.
Maik
mam ten sam problem. VS2013 miał przycisk, który można było kliknąć, ale VS2015 nie ma tego przycisku.
Spongman

Odpowiedzi:

113

Z forum MSDN :

To nie jest błąd sam w sobie, ale raczej cecha twojego debugera. Niektóre właściwości wymagają wykonania kodu w celu odczytania właściwości, ale jeśli wymaga to interakcji między wątkami, może być konieczne uruchomienie innych wątków. Debugger nie robi tego automatycznie, ale z pewnością może, za Twoją zgodą. Wystarczy kliknąć małą ikonę oceny, aby uruchomić kod i ocenić właściwość.

wprowadź opis obrazu tutaj

Więcej informacji na temat tego zachowania można znaleźć w tym znakomitym artykule

MUG4N
źródło
9
Przeczytałem ten artykuł. Nie mam takiego przycisku do kliknięcia, więc nie do końca mam problem. Dziwne jest to, że działało, odkąd dzisiaj zaktualizowałem program Visual Studio 2015 RC.
Maik
1
Ten sam problem tutaj: stackoverflow.com/questions/4460206/ ...
MUG4N
4
Jeśli nie widzisz żadnej ikony, spróbuj zmodyfikować zmienną / polecenie, aby wykonać zapytanie z okna obserwacyjnego, zamiast używać menu rozwijanego do eksploracji jego właściwości. Na przykład dodanie .ToList()lub .Any().
Hp93,
4
Nie wiem dlaczego, ale wywołanie .ToList () w moim zapytaniu rozwiązało problem
J.Kirk.
1
@ J.Kirk. Znalazłem to samo - dzięki! I był przy użyciu vara IEnumerable<T>i właśnie przypisanie db.AGENCY_TABLE.OrderBy(e => e.Name);- ale raz użyłem varz .ToList()(lub List<T>z .ToList()działa również), to ujawnia wynik!
vapcguy
23

Napotkałem ten problem, próbując po prostu pobrać elementy z tabeli o nazwie „AGENCY” za pomocą Entity Framework:

var agencies = db.AGENCY.OrderBy(e => e.FULLNAME);

wprowadź opis obrazu tutaj

Najechanie kursorem na agencje w trybie debugowania, kliknięcie, aby rozwinąć opcje, i kliknięcie Wyniki dałoby przerażające „Ocena funkcji wymaga uruchomienia wszystkich wątków” z ikoną „Nie wchodź” na końcu, na której kliknięcie nic nie dało.

2 możliwe rozwiązania:

  1. Dodaj .ToList()na końcu:

    var agencies = db.AGENCY_TABLE.OrderBy(e => e.FULLNAME).ToList();

    List<AGENCY_TABLE> agencies = db.AGENCY_TABLE.OrderBy(e => e.FULLNAME).ToList();

    Podziękowania dla Hp93 za pomoc w znalezieniu tego rozwiązania. W komentarzach do odpowiedzi MUG4N, w której znalazłem to rozwiązanie, wspomina również o próbowaniu .Any()zamiast .ToList(), ale to daje wartość logiczną zamiast <T>, jak <AGENCY>jest, więc prawdopodobnie nie pomoże.

  2. Obejście - wypróbuj inną ścieżkę w opcjach debugowania. Okazało się, że mogę kliknąć „Członkowie niepubliczni”> „_internalQuery”> ObjectQuery> Widok wyników i uzyskać w ten sposób moje wartości.

wprowadź opis obrazu tutaj

vapcguy
źródło
9

MUG4N rzeczywiście dostarczył poprawną odpowiedź, jednak jeśli najedziesz kursorem na wiersz kodu w debugowaniu, możesz patrzeć na coś podobnego do poniższego. Jeśli tak, kliknij małą ikonę ponownej oceny podświetloną na poniższym obrazku ...

wprowadź opis obrazu tutaj

NB : Otrzymałem ten obraz przez przypięcie, zwykle ponownie oceniam ikonę w środku okna, a nie w lewej kolumnie.

Ewan
źródło
To załatwiło sprawę dla mnie. Nie mogę uwierzyć, że tego nie próbowałem, dzięki za odpowiedź.
petey m
2

Powinieneś wykonać bezpieczne wywołanie wątku, ponieważ dostęp do formantów formularzy systemu Windows nie jest bezpieczny dla wątków w wielowątkowości. To jest mój prosty kod, który sprawia, że ​​wątek jest bezpieczny i ustawia pasek postępu.

public partial class Form1 : Form
{// This delegate enables asynchronous calls for setting  
    // the text property on a TextBox control.  
    delegate void StringArgReturningVoidDelegate(string text);
    private Thread demoThread = null;

    public int Progresscount = 0;
    static EventWaitHandle waithandler = new AutoResetEvent(false);
    public Form1()
    {
        InitializeComponent();
    }
    public static bool CheckForInternetConnection()
    {
        try
        {


            using (var client = new WebClient())
            {
                using (var stream = client.OpenRead("http://www.google.com"))
                {
                    return true;
                }
            }
        }
        catch
        {
            return false;
        }
    }

    public  void Progressincrement()
    {

        waithandler.WaitOne();
        while (CheckForInternetConnection()==true)
        {
            if (Progresscount==100)

            {
                break;
            }
            SetLabel("Connected");
            Progresscount += 1;

       SetProgress(Progresscount.ToString());
            Thread.Sleep(TimeSpan.FromSeconds(1));
        }
        if (Progresscount <100)
        {
            Startthread();
        }
        SetLabel("Completed");


    }

  public  void Startthread ()
        {

   this.demoThread=   new Thread(new ThreadStart(Progressincrement));
        this.demoThread.Start();
     SetLabel("Waiting for connection");
        while (CheckForInternetConnection() == false) ;

        waithandler.Set();
    }
    private void SetLabel(string text)
    {
        // InvokeRequired required compares the thread ID of the  
        // calling thread to the thread ID of the creating thread.  
        // If these threads are different, it returns true.  
        if (this.label1.InvokeRequired)
        {
            StringArgReturningVoidDelegate d = new StringArgReturningVoidDelegate(SetLabel);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            this.label1.Text = text;
        }
    }
    private void SetProgress(string Value)
    {
        // InvokeRequired required compares the thread ID of the  
        // calling thread to the thread ID of the creating thread.  
        // If these threads are different, it returns true.  
        if (this.progressBar1.InvokeRequired)
        {
            StringArgReturningVoidDelegate d = new StringArgReturningVoidDelegate(SetProgress);
            this.Invoke(d, new object[] {Value});
        }
        else
        {
            this.progressBar1.Value = Convert.ToInt32(Value);
        }
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        Startthread();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show("Responsive");
    }
}

Po więcej informacji MSDN

TAHA SULTAN TEMURI
źródło
1

Używam następnego obejścia, aby przejść:

var OtherThreadField = "";
Invoke(new MethodInvoker(delegate
                    {
                        OtherThreadField = ExecuteNeededMEthod();
                    }));

Teraz mam wartość dla OtherThreadField.

sh2dow
źródło