web-dev-qa-db-fra.com

Visual Studio pendant le débogage: l'évaluation de la fonction nécessite l'exécution de tous les threads

Je reçois soudainement une erreur étrange lors du débogage. Jusqu'à présent, la variable dans les fenêtres de surveillance était correctement affichée. Maintenant, je reçois toujours le message d'erreur dans les fenêtres de surveillance:

L'évaluation de la fonction nécessite l'exécution de tous les threads

Je ne peux plus vérifier aucune variable. Je ne suis pas explicite de travailler avec des threads. Que puis-je faire pour que cela fonctionne à nouveau?

J'ai déjà désactivé, comme mentionné dans certains forums, la fonction: "Activer l'évaluation des propriétés et autres appels de fonction implicites" dans la fenêtre d'options du débogueur. Mais sans succès, alors j'obtiens l'erreur:

Erreur Evaluation de la fonction implicite désactivée par l'utilisateur

62
Maik

Depuis le forum msdn :

Ce n'est pas une erreur en soi, mais plutôt une fonctionnalité de votre débogueur. Certaines propriétés nécessitent l'exécution d'un code pour que la propriété puisse être lue, mais si cela nécessite une interaction entre threads, il est possible que d'autres threads doivent également s'exécuter. Le débogueur ne le fait pas automatiquement, mais peut certainement, avec votre permission. Il suffit de cliquer sur la petite icône d'évaluation pour lancer votre code et évaluer la propriété.

enter image description here

Pour plus de détails sur ce comportement, consultez cet excelent article

75
MUG4N

J'ai rencontré ce problème lorsque j'essayais simplement d'obtenir des éléments d'une table appelée "AGENCY" à l'aide d'Entity Framework:

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

enter image description here

En survolant les agences en mode débogage, en cliquant pour développer les options, et en cliquant sur Résultats, vous obtiendrez le message redouté "L'évaluation de la fonction nécessite l'exécution de tous les threads" avec une icône "Ne pas entrer" à la fin, sur laquelle cliquer n'a fait rien.

2 solutions possibles:

  1. Ajouter .ToList() à la fin:

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

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

    Le mérite en revient à HP93 de m'avoir aidé à trouver cette solution. Dans les commentaires sur la réponse de MUG4N où j'ai trouvé cette solution, il est également mentionné d'essayer .Any() au lieu de .ToList(), mais cela donne un booléen au lieu d'un <T>, Comme <AGENCY> L'est, donc cela ne vous aiderait probablement pas.

  2. Solution de contournement - essayez un autre chemin dans les options de débogage. J'ai découvert que je pouvais cliquer sur "Afficher les résultats non publics"> "_internalQuery"> ObjectQuery> Results et obtenir ainsi mes valeurs.

enter image description here

11
vapcguy

MUG4N a bien fourni une réponse correcte, cependant, si vous passez la souris sur la ligne de code dans le débogage, il se peut que vous regardiez quelque chose comme ce qui suit. Si c'est le cas, cliquez sur la petite icône de réévaluation mise en surbrillance dans l'image ci-dessous ...

enter image description here

[~ # ~] nb [~ # ~] : j'ai obtenu cette image en épinglant, normalement les icones de réévaluation sont au milieu de la fenêtre. et pas dans la colonne de gauche.

6
Ewan

Vous devez effectuer un appel thread-safe car l'accès aux contrôles de formulaire Windows n'est pas Thread safe en multithreading. C’est mon code simple qui fait de Thread un appel sécurisé et définit la barre de progression.

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");
    }
}

Pour plus d'informations MSDN

1

J'utilise la prochaine solution de contournement pour passer:

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

Maintenant, j'ai une valeur pour OtherThreadField.

1
sh2dow