调试期间的Visual Studio:函数评估需要所有线程运行

140

在调试过程中突然出现了一个奇怪的错误。到目前为止,在监视窗口中显示的变量一直都是正确的。现在,在监视窗口中总是显示以下错误信息:

函数评估需要所有线程运行

我再也不能检查任何变量了。我没有明确地使用线程。我该怎么做才能让它再次工作?

我已经像一些论坛中提到的那样,在调试器的选项窗口中禁用了“启用属性评估和其他隐式函数调用”功能。但是没有成功,并且它给了我这个错误:

用户禁用了隐式函数评估


1
获取列表的那个点:你重启了Visual Studio吗? - MUG4N
1
是的,我做了。重新启动后仍然出现同样的问题。 - Maik
1
请查看以下链接:https://dev59.com/0m855IYBdhLWcg3wik-D - MUG4N
1
即使它能够工作,这也不可能是解决方案,因为我想使用NET 4.x框架。我不想因为这个问题而降级。我想知道为什么它在一段时间前还能工作。 - Maik
1
我遇到了同样的问题。在VS2013中,你可以点击一个按钮,但是在VS2015中并没有这个按钮。 - Spongman
8个回答

159

来自msdn论坛:

这并不是错误本身,而更像是您的调试器的一个特性。

有些属性需要执行代码才能读取属性,但如果这需要跨线程交互,则其他线程也可能需要运行。调试器不会自动执行此操作,但在您的许可下可以执行。

只需单击小的求值图标,它就会运行您的代码并评估该属性。

enter image description here

如需了解更多有关此行为的详细信息,请查看这篇优秀的文章:
为什么会出现“函数评估需要所有线程运行” | 微软学习


17
我已阅读此文章。我没有这样的按钮可以点击,所以我的问题不完全相同。奇怪的是,自从我今天升级到Visual Studio 2015 RC以来,它一直在工作。 - Maik
2
这里有相同的问题:https://dev59.com/FG855IYBdhLWcg3wPBtx - MUG4N
12
如果您没有看到任何图标,请尝试修改变量/命令从监视窗口执行查询,而不是使用下拉菜单来查看其属性。例如,添加.ToList().Any() - Hp93
12
我不确定原因,但在我的查询上调用.ToList()解决了问题。 - J.Kirk.
4
文章链接已失效。 - Hrvoje
显示剩余5条评论

39

当我使用Entity Framework从名为“AGENCY”的表中获取项目时,遇到了这个问题:

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

输入图像描述

在调试模式下悬停在机构上,单击展开选项,然后单击“结果”会出现恐怖的“函数评估需要所有线程运行”的错误,并在末尾显示一个“不可进入”图标,单击它没有任何反应。

2个可能的解决方案:

  1. 在结尾处添加.ToList()

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

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

    感谢Hp93帮助我找到这个解决方案。在我发现这个解决方案的MUG4N的答案评论中,也提到了尝试使用.Any()而非.ToList(),但是这将得到一个布尔值而不是像<AGENCY>那样的<T>,所以它可能没有什么用。

  2. 解决办法-尝试调试选项中的其他路径。 我发现我可以单击“非公共成员”>“_internalQuery”> ObjectQuery >“结果视图”来获取我的值。

输入图像描述


12

MUG4N确实提供了正确的答案,但是如果您在调试时将鼠标悬停在代码行上,可能会看到以下内容。如果是这样,请单击下面图像中突出显示的重新评估图标...

enter image description here

NB:我通过固定获得了这张图片,通常重新评估图标位于窗口的中央而不是左侧列下方。


1
这对我很有帮助。我简直不敢相信我没有尝试过这个,感谢你的答案。 - petey m

3

这并不是一个错误,而更像是您的调试器的一个特性。
调试器不会自动执行此操作,但可以在用户许可下执行。只需单击小的空格图标,它将运行代码并评估属性。

参考下面的截图


1
但这并不是一直以来的行为,而且每次我想评估一个项目时都需要按住这个键有点烦人。有一个自动执行此操作的选项将是很好的,并提供重新恢复先前行为的机会。 - user3502865

3

在多线程中访问Windows表单控件不是线程安全的,因此您应该进行线程安全调用。 以下是我的简单代码,它可以进行线程安全调用并设置进度条。

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

欲了解更多信息,请参阅MSDN


2
我使用下一个解决方法来通过:
var OtherThreadField = "";
Invoke(new MethodInvoker(delegate
                    {
                        OtherThreadField = ExecuteNeededMEthod();
                    }));

现在我有一个OtherThreadField的值。

1

对我来说,这是在尝试中断访问由一个Settings类包含的复杂对象实例的行时发生的。

在以下if上设置断点会导致Settings.Default.FindSettings的值为"The function evaluation requires all threads to run."。如果我按下force eval按钮,则它为空。点击force eval按钮或不点击就进入if块并初始化对象。如果我删除断点并在if块后添加新的断点,则Settings.Default.FindSettings会正确反序列化,具有预期的值。

if (Settings.Default.FindSettings == null)
{
    Settings.Default.FindSettings = new FindSettings();
}

经过反复试验,我在上述if块之前添加了以下代码以访问设置以避免崩溃。这似乎可以可靠地解决问题。我不需要它在生产中,所以我用条件编译指令进行包装。我在代码中有一个注释而不是一个无意义的丢弃:
#if DEBUG
    var _ = Settings.Default.FindSettings;
#endif

我不确定上述代码行是否会在生产环境中被优化掉,因为它具有副作用。由于我只需要在调试时使用它,所以我没有进行检查。


1

我曾经遇到过同样的问题并解决了。这个问题是由于用户名和密码引起的,在SQL连接中有用户和密码,但在代码中没有用户和密码。所以我启用了用户和密码,问题得到了解决。


1
在假设这是相同的之前,你或许应该问一些问题?可能你遇到了与mssql使用相关的类似问题,但是问题中没有涉及到rdbms使用,而你显然解决的问题是由@mug4n解释的。因此,如果你的解决方案与问题有关,那么它可能会更有帮助,但请先通过评论确保它至少与问题相关。否则就像“我感觉想要点什么”回答“买点茶”...现在你可能会很幸运,这是一个完美的答案,但是... :) - T. Nielsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接