无法从BackgroundWorker中访问表单句柄

时间:2015-05-04 04:53:53

标签: c# .net multithreading backgroundworker

我正在经历一些奇怪的事情。我可以从我的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之外的某些属性(或者看起来如此)?

1 个答案:

答案 0 :(得分:4)

“跨线程操作无效”InvalidOperationException是常态。我发现由于我不知道的原因,一些控件的成员可以从错误的线程中成功调用,但是the documentation非常清楚哪些成员可以工作:

  

除了InvokeRequired属性之外,控件上还有四个可以线程安全调用的方法:Invoke,BeginInvoke,EndInvoke和CreateGraphics

换句话说,你问题中真正的谜团不是为什么你试图调用Handle属性getter时会遇到异常。这就是为什么你没有获得调用TextName getter的异常的原因。

就个人而言,我发现这个神秘感不那么有趣。底线是,如果您需要在Handle事件处理程序中检索DoWork属性,则需要使用Control.Invoke()方法访问UI线程上的属性并将其返回回到工作线程中的代码。或者,在启动worker之前检索句柄值,并通过您选择的机制将其提供给DoWork事件处理程序。


修改

即使我没有找到所有有趣的谜,我还是继续看看referencesource.microsoft.com网站,我可以看到the Text property作为一个明确的例外来处理“没有跨线程调用”规则。甚至有一条评论说“可以调用GetWindowText跨线程”,而那里的代码(在internal WindowText属性中)使用MultithreadSafeCallScope类来禁用跨线程检查的持续时间。操作。

如果记录得更好(即在MSDN本身上)会很好,但是你去了。 :)