【问题标题】:How to create multiple threaded Forms as MDIChild如何将多线程表单创建为 MDIChild
【发布时间】:2012-09-20 04:04:05
【问题描述】:

是否可以有多个线程表单作为 MDIChild?我有一个 MdiChild 形式的 ActiveX 控件,它可能会占用大量处理 CPU,并且希望通过使用下面的示例代码使一个控件不会影响另一个控件。但是行 frmDoc.MdiParent = Me 会抛出跨线程异常。

Dim frmDoc As MDIChild
Dim newThread As New Thread(
    Sub()
        frmDoc = New MDIChild
        frmDoc.MdiParent = Me '<- this line throws cross threading exception.
        Application.Run(frmDoc)
    End Sub
)
newThread.IsBackground = True
newThread.SetApartmentState(ApartmentState.STA)
newThread.Start()

抛出 System.InvalidOperationException 未处理:

Message=Cross-thread operation not valid: 
  Control 'FormMdiApp' accessed from a thread other than the thread it was created on.
Source=System.Windows.Forms

【问题讨论】:

  • 你能把这个带有ActiveX控件的表单做成非MDI表单吗?
  • 只是在想,这可能在 C++ MFC 应用程序中完成吗?
  • 我不了解 C++ MFC,但如果您只是将 frmDoc 更改为非 MDI 子窗体,它应该可以工作。当然,当您需要从另一个线程访问它时,您必须小心Invoke
  • 我认为我唯一的选择是关注“MTMDI 示例:演示 MFC 用户界面线程”msdn.microsoft.com/en-us/library/s3wsyb55%28VS.80%29.aspx
  • 显示更多关于“线程异常”的细节。

标签: .net vb.net


【解决方案1】:

只能在主事件循环中初始化和访问 GUI 元素。您可以异步或在后台线程中处理繁重的计算。

【讨论】:

  • 可以有多个表单,每个表单都有自己的线程和消息循环,但我认为它不适用于 MDI 子级。
  • @Blorgbeard,这样做合理吗?我从来没有在多个线程中遇到过多种形式。你能举出例子吗?谢谢。
  • 是的,这是可行的。基本上你做 OP 正在做的事情,除了 MDI 表单。在一个新的 (STA) 线程中,您创建一个表单,然后将其传递给 Application.Run,​​它会为您设置一个新的事件循环。您需要小心调用任何跨线程调用,但它确实有效。
  • 例如谷歌浏览器在单独的进程中运行每个标签
  • @walter:Google Chrome 也不能在 WinForms 上运行。
【解决方案2】:

试试BackgroundWorker http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.95).aspx

执行 DoWork 事件中的所有繁重操作,并使用 ProgressChanged/RunWorkerCompleted 事件更新 UI 元素。

【讨论】:

    【解决方案3】:

    关于如何实现的可用选项

    刚刚找到一篇不错的msdn支持文章How To Create Windows in a Multithreaded Application

    创建一个窗口可以强制一个隐式的AttachThreadInput(),当一个 父窗口在一个线程中创建,子窗口正在 在另一个线程中创建。在创建(或设置)窗口时 具有父子关系的单独线程,输入队列 已附上。

    更多信息可以在 Walkthrough: Supporting COM Interop by Displaying Each Windows Form on Its Own Thread

    Spawn a new thread to open a new window and close it from a different thread提出了类似的问题

    但是,幸运的是,这些都没有关于子表单的任何内容。

    更新:刚刚在演练代码中发现了错误;但总的来说,这个示例有一些不错的想法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-16
      • 1970-01-01
      • 2022-10-31
      • 1970-01-01
      相关资源
      最近更新 更多