下面的等待项在await
点尚未完成,并且未捕获UI上下文。这意味着随后的UI修改代码将在另一个线程(在这种情况下为线程池线程)中调用。
private async void Button1_Click(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
sb.Append($"{Thread.CurrentThread.ManagedThreadId}, ");
Task t = Task.Delay(1000);
await t.ConfigureAwait(false);
sb.Append($"{Thread.CurrentThread.ManagedThreadId}");
Text = sb.ToString();
}
上面的代码运行没有问题。运行时没有错误。
为什么允许在非UI线程中修改UI组件? 我的理解有问题吗?
答案 0 :(得分:3)
默认情况下,除非附加了调试器,否则在Winforms中禁用跨线程检查。可以看到in the initialization of the checkForIllegalCrossThreadCalls
field:
private static bool checkForIllegalCrossThreadCalls = Debugger.IsAttached;
如果我不得不猜测,我会说这是保持复古兼容性的一种尝试。 .NET 1.1没有跨线程检查(早在我离开时,我一直想知道为什么我的应用程序在几个小时后就会神秘崩溃),它们是与.NET 2.0一起添加的。但这是一个巨大的突破性变化,我想这就是他们选择加入的原因。使用WPF,马上就引入了跨线程检查,因此它们可以为每个人激活。
有鉴于此,我强烈建议您在任何winform项目中手动启用跨线程检查,方法是将此行添加到入口点:
[STAThread]
static void Main()
{
Control.CheckForIllegalCrossThreadCalls = true;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}