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

问题描述 投票:0回答:9

我在调试时突然遇到一个奇怪的错误。到目前为止,观察窗口中的变量已正确显示。现在我总是在监视窗口中收到此错误消息:

函数求值需要所有线程运行

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

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

错误隐式函数评估被用户禁用

c# visual-studio-debugging
9个回答
159
投票

来自 msdn 论坛:

这本身并不是一个错误,而是调试器的一个功能。

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

只需单击小评估图标,它将运行您的代码并评估属性。

enter image description here

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


39
投票

我在尝试使用实体框架从名为“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()
    ,但这给出了一个布尔值而不是
    <T>
    ,就像
    <AGENCY>
    一样,所以它可能没有帮助。

  2. 解决方法 - 在调试选项中尝试不同的路径。我发现我可以单击“非公共成员”>“_internalQuery”> ObjectQuery > 结果视图并以这种方式获取我的值。


12
投票

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

NB:我通过固定获得此图像,通常重新评估图标位于窗口中间,而不是左栏下方。


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


3
投票

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

Check below screenshot for reference


2
投票

我使用下一个解决方法来通过:

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

现在我有了 OtherThreadField 的值。


1
投票

我遇到了同样的问题并解决了。问题是由于用户名和密码而出现的,在 SQL 连接中有用户和密码,但在代码中没有用户和密码。所以我启用了用户和密码,问题就解决了


1
投票

对我来说,当尝试中断访问设置类包含的复杂对象实例的行时,就会发生这种情况。

以下

if
上的断点会导致
Settings.Default.FindSettings
,其值为“函数求值需要所有线程运行”。如果我按下强制评估按钮,则它为空。单击或不单击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

我不确定上面的代码是否会在生产中优化,因为它有副作用。由于我只在调试时需要它,所以我没有检查。


0
投票

我在 VSCODE+'C# Dev Kit' 中调试 C# 时遇到此“错误”。有谁知道如何在 VSCODE 上启用此功能吗?

© www.soinside.com 2019 - 2024. All rights reserved.