我在调试时突然遇到一个奇怪的错误。到目前为止,观察窗口中的变量已正确显示。现在我总是在监视窗口中收到此错误消息:
函数求值需要所有线程运行
我无法再检查任何变量。我没有明确地使用线程。我该怎么做才能让它再次工作?
正如某些论坛中提到的,我已经禁用了调试器选项窗口中的“启用属性评估和其他隐式函数调用”功能。但没有成功,它给了我这个错误:
错误隐式函数评估被用户禁用
来自 msdn 论坛:
这本身并不是一个错误,而是调试器的一个功能。某些属性需要执行代码才能读取属性,但如果这需要跨线程交互,则其他线程可能也必须运行。调试器不会自动执行此操作,但在您的许可下当然可以。
只需单击小评估图标,它将运行您的代码并评估属性。
有关此行为的更多详细信息,请查看这篇优秀文章:
为什么会出现“函数求值需要所有线程运行” |微软学习
我在尝试使用实体框架从名为“AGENCY”的表中获取项目时遇到了这个问题:
var agencies = db.AGENCY.OrderBy(e => e.FULLNAME);
将鼠标悬停在调试模式下的机构上,单击以展开选项,然后单击“结果”将给出可怕的“函数评估需要所有线程运行”,并在末尾带有“请勿输入”图标,单击该图标不会执行任何操作.
2种可能的解决方案:
最后添加
.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>
一样,所以它可能没有帮助。 解决方法 - 在调试选项中尝试不同的路径。我发现我可以单击“非公共成员”>“_internalQuery”> ObjectQuery > 结果视图并以这种方式获取我的值。
您应该进行线程安全调用,因为在多线程中访问 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
这不是错误,而是调试器的一个功能。
调试器不会自动执行此操作,但在用户许可的情况下当然可以。只需单击小空间图标,它将运行代码并评估属性。
我使用下一个解决方法来通过:
var OtherThreadField = "";
Invoke(new MethodInvoker(delegate
{
OtherThreadField = ExecuteNeededMEthod();
}));
现在我有了 OtherThreadField 的值。
我遇到了同样的问题并解决了。问题是由于用户名和密码而出现的,在 SQL 连接中有用户和密码,但在代码中没有用户和密码。所以我启用了用户和密码,问题就解决了
对我来说,当尝试中断访问设置类包含的复杂对象实例的行时,就会发生这种情况。
以下
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
我不确定上面的代码是否会在生产中优化,因为它有副作用。由于我只在调试时需要它,所以我没有检查。
我在 VSCODE+'C# Dev Kit' 中调试 C# 时遇到此“错误”。有谁知道如何在 VSCODE 上启用此功能吗?