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.