【问题标题】:Cannot access form handle from within BackgroundWorker无法从 BackgroundWorker 中访问表单句柄
【发布时间】:2015-05-04 04:53:52
【问题描述】:

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

【问题讨论】:

  • @GrantWinney 我确实需要用于调用本机 api 的句柄。不过,情况不再如此。我已经编辑了我的答案。

标签: c# .net multithreading backgroundworker


【解决方案1】:

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

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

换句话说,您问题的真正奥秘不是为什么您在尝试调用 Handle 属性获取器时遇到异常。这就是为什么您不会在调用 Text 或 Name getter 时遇到异常。

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


编辑:

尽管我并不觉得这个谜很有趣,但我还是继续查看了 referencesource.microsoft.com 网站,我可以看到 the Text property 被作为“否”的明确例外处理跨线程调用”规则。甚至还有一条评论说“可以跨线程调用 GetWindowText”,并且那里的代码(在internal WindowText 属性中)使用MultithreadSafeCallScope 类在操作期间禁用跨线程检查。

如果这有更好的文档记录(即在 MSDN 本身上),那就太好了,但是你去吧。 :)

【讨论】:

    猜你喜欢
    • 2014-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多