从WinForms BackgroundWorker创建WPF窗口

时间:2009-06-17 18:09:12

标签: wpf backgroundworker

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

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

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

  

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

谷歌搜索让我this discussion。 (除了Stack Overflow之外,Jon Skeet还回答了其他网站上的问题!)他链接到了this article,其中说明了

  

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?

2 个答案:

答案 0 :(得分:4)

可以使用WPF的后台工作者,这不是你的问题。

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

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

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

答案 1 :(得分: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()
}