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


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


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


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


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.


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


1

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

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

Teraz mam wartość dla OtherThreadField.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.