我正在经历一些奇怪的事情。我可以从我的BackgroundWorker DoWork
方法中访问我的表单的许多控件,但尝试在其中任何一个上获取Handle
属性都会让我“跨线程操作无效”。
例如:
private void backgroundWorker1_DoWork(object sender,
System.ComponentModel.DoWorkEventArgs e)
{
var usefulText = textbox1.Text;
var formName = this.Name;
var formHandle = this.Handle; // this line won't work
}
为什么我可以访问除Handle
之外的某些属性(或者看起来如此)?
答案 0 :(得分:4)
“跨线程操作无效”InvalidOperationException
是常态。我发现由于我不知道的原因,一些控件的成员可以从错误的线程中成功调用,但是the documentation非常清楚哪些成员可以工作:
除了InvokeRequired属性之外,控件上还有四个可以线程安全调用的方法:Invoke,BeginInvoke,EndInvoke和CreateGraphics
换句话说,你问题中真正的谜团不是为什么你试图调用Handle
属性getter时会遇到异常。这就是为什么你没有获得调用Text
或Name
getter的异常的原因。
就个人而言,我发现这个神秘感不那么有趣。底线是,如果您需要在Handle
事件处理程序中检索DoWork
属性,则需要使用Control.Invoke()
方法访问UI线程上的属性并将其返回回到工作线程中的代码。或者,在启动worker之前检索句柄值,并通过您选择的机制将其提供给DoWork
事件处理程序。
修改强>
即使我没有找到所有有趣的谜,我还是继续看看referencesource.microsoft.com网站,我可以看到the Text
property作为一个明确的例外来处理“没有跨线程调用”规则。甚至有一条评论说“可以调用GetWindowText跨线程”,而那里的代码(在internal WindowText
属性中)使用MultithreadSafeCallScope
类来禁用跨线程检查的持续时间。操作。
如果记录得更好(即在MSDN本身上)会很好,但是你去了。 :)