3

我有一个 WPF dll,其中包含许多 Window 类并公开显示这些窗口的方法。

我还有一个单独的 WinForms 项目,它在 BackgroundWorker 组件的 DoWork 方法中调用 WPF 项目中的这些方法之一。

在实例化 WPF 窗口的代码行中,我收到以下运行时错误:

调用线程必须是 STA,因为许多 UI 组件都需要这个。

谷歌搜索让我进入了这个讨论。(事实证明,除了 Stack Overflow,Jon Skeet 还回答了其他网站上的问题!)他链接到这篇文章,其中指出

BackgroundWorker 组件适用于 WPF ...

那篇文章还提到了使用 DispatcherObject 类,但我不明白如何使它工作,我宁愿继续使用我的 BackgroundWorker 组件。

作为测试用例,我想出了以下代码来重现错误。在 WPF 类库中,这里是 Window1.xaml.vb 中的代码

Partial Public Class Window1

    Public Shared Function ShowMe() As Boolean?
        Dim w = New Window1 'Error appears on this line.
        Return w.ShowDialog()
    End Function

End Class

在 WinForms 应用程序中,这里是 Form1.vb 中的代码

Imports System.ComponentModel

Public Class Form1

    Private WithEvents worker As BackgroundWorker
    Private Sub doWord(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles worker.DoWork
        WpfLibrary.Window1.ShowMe()
    End Sub
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        worker = New BackgroundWorker
        worker.RunWorkerAsync()
    End Sub
End Class

即使将 BackgroundWorker 组件放在 Window1.xaml.vb 本身中,也会发生相同的错误。那么,那篇文章是不是错了,我真的不能将 BackgroundWorker 与 WPF 一起使用?或者我还需要做些什么才能让它工作吗?

如果 BackgroundWorker 不起作用,那么我将如何替换上面 Form1.vb 中的代码以使用 Dispatcher 呢?

4

2 回答 2

4

可以在 WPF 中使用后台工作人员,这不是您的问题。

您的问题是您无法在 winform 或 WPF 应用程序中执行从主 UI 线程外部更新 UI 的任何任务,并且 BackgroundWorker 的 DoWork 方法在不同的线程中运行。

因此,您必须在启动 BackgroundWorker 之前或在其 RunWorkerCompleted 事件中,在 BackgroundWorker 的后台线程之外打开新窗口。

在不知道打开窗口的调用周围的代码的情况下,我很难提供进一步的建议,但我希望这能为您指明正确的方向。

于 2009-06-17T18:16:44.890 回答
3

您的工作人员还可以创建自己的线程,将该线程标记为 STA,然后调用Thread.Join()以等待它终止。然后,您将能够在新线程上创建并显示窗口(尽管请注意,如果不使用 Dispatcher,其他线程将无法与其交互)。

C# 中的示例:

Thread workerThread = new Thread(ShowMyWindow);
workerThread.SetApartmentState(ApartmentState.STA);
workerThread.Start();
workerThread.Join();

进而:

private void ShowMyWindow()
{
    WpfLibrary.Window1.ShowMe()
}
于 2009-06-17T18:21:47.923 回答