从辅助线程工作(WinForms)更新GUI,为什么?

时间:2019-12-11 14:43:08

标签: multithreading winforms controls

WinForms (VS2015 / .NET 4.6)

在我的后台线程中

 System.Threading.Tasks.Task.Run(() =>
 {
    ...
    _callback?.Progress("abcd");
    ...
 });

我调用GUI(_callback),它在Form类中实现了一个接口。 在这里,我修改了文本框,进度条等值。

void IWorkerCallback.Log(string message)
{
    _textBoxLog.AppendText($"{message}{Environment.NewLine}");
    ++_progressBar.Value;
    .... etc...
}

一切正常!
如果我闯入调试器,我会发现Form.IWorkerCallback.Log()函数是在工作线程上下文中执行的(在“线程调试”窗口中)。

到处都说,您只能在GUI线程(创建它们的地方)上更改GUI项,否则您将获得System.InvalidOperationException的{​​{1}}异常

但是对我来说很好。

你能解释为什么吗?

谢谢

1 个答案:

答案 0 :(得分:1)

从另一个线程运行UI调用是未定义的行为。它可能行不通。要在跨线程调用中获得一致的失败,请在程序的开头设置Control.CheckForIllegalCrossThreadCalls = true;

https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.checkforillegalcrossthreadcalls?view=netframework-4.8

来自MSDN文档:

  

当控件的创建线程以外的其他线程尝试访问该控件的方法或属性之一时,通常会导致不可预测的结果。常见的无效线程活动是对访问控件的Handle属性的错误线程的调用。将CheckForIllegalCrossThreadCalls设置为true可以更轻松地查找和诊断此线程活动。

在较低的Windows API级别上,可能会成功执行不使用线程本地存储或任何其他线程特定资源的跨线程UI调用。但是,我们仍然存在线程同步问题,因此结果也是不确定的。