-1

我们在 Windows.Forms 解决方案中创建了几个线程。

我们还有一个 BrowserControl(是的,它是 OAUTH),当然我发现调试问题 -

跨线程操作无效:控件“xxForm”从创建它的线程以外的线程访问

然而我叫'正确'

xxForm.Show()

通过确保它包含在调用调用中

.Invoke(新的 MethodInvoker())

我仍然得到线程问题。我可以做其他所有事情(Focus,BringToFront),这是显示错误。

此外,GUI 永远不会得到浏览器的响应和显示。在 VS 调试器中,我得到了上述线程错误(后台线程的公寓状态 == MTA)。当作为 EXE 运行时,相同的代码具有 STA 的线程 aparement,并且 GUI 在调试时永远不会显示,但如果我直接运行 EXE,则没有线程问题,浏览器控件永远不会响应输入。

Spo的问题是:

  • 为什么 VS / EXE 中的行为不同?
  • 如何在 VS 中调试?
  • BrowserControl 是否可以与多个线程一起使用?

更新

是的,我知道没有代码 - 它太长了。我会看看我能做什么。

另外,请在发布答案之前阅读问题。我在 UI 线程上调用后台线程。那不是问题。这对结果没有影响。我会否决建议的答案。

还有一些希望 - 我已经搜索了很多小时。它链接了消息泵。除非消息泵正在运行,否则不会收到 DocumentCompleted 事件。

更新 2 我管理的最好的是伪代码:

程序:

 startWorkQueue
 LoadForm (don't show)

线程1:

 addToQueue

线程2:

 readFromQueue
 ShowForm (on occasion)

现在 ShowForm 方法位于 Windows.Form 控件上。在此范围内,任何调用都是通过 Invoke 进行的,因此尽管第二个线程调用 ShowForm,但实际的 .Show() 等调用仍在 UI 线程上。

那么我错过了什么?我只是不明白为什么会有跨线程异常......

4

2 回答 2

1

好的,我已经知道发生了什么,我会在这里发布以供参考。我希望它对将来的人有所帮助。

我们对 vanilla Forms 应用程序有一些不同的限制——我们的 Forms 是在主线程上创建的,但 Show() 在不同的线程上调用。我们也没有启动 UI - 我们坐在后台,有时会通过 UI 提示对事件做出反应。

因此,我们遇到了许多问题。我不会将它们全部列出来,而是详细说明我们的要点:

应用程序运行

  • 如果决定在您的应用程序开始时不显示表单……那么您需要仔细考虑线程(请参阅 Form.Show 注释)

表格显示

  • 这会完成所有资源分配等,而不是 Load/ctor
  • 执行句柄创建/资源分配

处理创建

  • Hwnd
  • 如果我们尝试在某些 Form 属性具有 Show(n) 之前访问它,那么您需要手动创建一个句柄(或创建一个异常)

    • 一样容易if (!IsHandleCreated) { CreateHandle(); }

然而

  • 这将创建控件/表单
  • 因此,控件/表单是在调用 Handle create 的线程上创建的
  • 这必须是与 Main 函数相同的 UI 线程 (STA)

    • 否则会发生很多奇怪的事情

所以

  • 您不受使用 Application.Run 的限制
  • 您可以访问 .Show 中的属性(但您可能需要先创建一个句柄)
  • 您可以从不同的线程调用 Show,但请确保仅在主线程上创建句柄

希望对您有所帮助,如果需要,我可以提供有关我们具体问题的更多详细信息。

各种帮助包括在日志中显示 ManagedThread 和 ProcessId 以及搜索 MSDN。

于 2013-01-07T09:21:07.557 回答
0

由于代码还没有粘贴,我想提醒你,在 WinForms 中,UI 元素应该只能在 UI 线程上访问。除了 UI 线程之外的任何其他线程都不应直接更新 UI 元素。

于 2013-01-02T15:52:58.523 回答