2009-06-17 13 views
3

私は、いくつかのWindowクラスを含み、それらのウィンドウを表示するメソッドを公開するWPF dllを持っています。WinForms BackgroundWorkerからWPFウィンドウを作成する

また、WPFプロジェクトでBackgroundWorkerコンポーネントのDoWorkメソッド内でこれらのメソッドの1つを呼び出す別のWinFormsプロジェクトもあります。 WPFウィンドウをインスタンス化するコードの行で

、私は、次のランタイムエラーを取得:

The calling thread must be STA, because many UI components require this.

Google検索がthis discussionにさせて頂いております。 (ジョンスキートはスタックオーバーフローに加えて、他のサイト上の質問に答えが判明!)彼は、記事はまた、DispatcherObjectにクラスを使用して言及しているが、私はことを確認する方法を理解していない

The BackgroundWorker component works well with WPF ...

を述べている、this articleにリンク私はBackgroundWorkerコンポーネントを使用し続けます。

テストケースとして、私はエラーを再現するために次のコードを考え出しました。 WPFのクラスライブラリに、ここ​​でのコードは、ここでコードはBackgroundWorkerのコンポーネントが配置されている場合でも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 

であり、リサイズアプリケーションで

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 

Window1.xaml.vb

でありますWindow1.xaml.vb自体で同じエラーが発生します。だから、その記事は間違っていて、私は実際にWPFでBackgroundWorkerを使用することはできませんか?それとも、それを働かせるために何か必要なことはありますか?

BackgroundWorkerが機能しない場合は、上記のForm1.vbのコードを代わりに使用してDispatcherを使用する方法はありますか。

答えて

4

は、WPFでバックグラウンドワーカーを使用していますが、それはあなたの問題ではありません。

winformまたはWPFアプリケーションのいずれかでメインUIスレッドの外部からUIを更新するタスクを実行できず、BackgroundWorkerのDoWorkメソッドが別のスレッドで実行されているという問題があります。

したがって、BackgroundWorkerを開始する前、またはそのRunWorkerCompletedイベントで、BackgroundWorkerのバックグラウンドスレッドの外側で新しいウィンドウを開く必要があります。

ウィンドウを開くための呼び出しを囲むコードがわからないと、私はさらにアドバイスすることが難しいですが、正しい方向に指してくれることを願っています。

+0

ありがとう! DoWorkイベントのコードをRunWorkerCompletedイベントにコピーしただけで動作します。 – CoderDennis

+0

FYI、RunWorkerCompletedはワーカーのスレッドではなくワーカーを開始したのと同じスレッドで実行されると思います。もしそうなら、あなたはBackgroundWorkerをまったく使用しないかもしれません。 –

+0

あなたはWPFで複数のUIスレッドを持つことができます(私がやったことがあります)。しかし、あなたのコントロール下にないので、BackgroundWorkerスレッドからUIを表示することは望ましくありません.ToolPoolはそのスレッドが何をいつ実行するかを決定します。通常のスレッドが必要で、STAに設定し、ThreadStartメソッドからApplication.Runを呼び出します。 –

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() 
} 
+0

コード内でどのように見えますか?スレッドはどのようにSTAとマークされていますか? – CoderDennis

+0

私はC#で例を追加しました。申し訳ありませんが、私はVBの例を実行するのに十分なVBは分かりませんが、SetApartmentState呼び出しが必要です。 –

+0

クール、ありがとう!私もC#で作業してきましたが、ほとんどのVB開発者はコード例を読むのに十分なC#を知っていると思います。私たちはbcsに書かれているものがほとんどです! – CoderDennis

関連する問題