2011-07-31 6 views
3

System.ComponentMode.BackgroundWorkerのDoWorkから「FlowDocument」WPFオブジェクトを作成しましたが、WPF UIスレッドでWPFオブジェクトにアクセスできません。BackgroundWorkerとWPF

using System; 
using System.Windows; 
using System.Windows.Documents; 
using System.ComponentModel; 
namespace WpfApplication1 
{ 
    public partial class MainWindow : Window 
    { 

     BackgroundWorker bw = new BackgroundWorker(); 

     public MainWindow() 
     { 
      InitializeComponent(); 

      bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
      bw.RunWorkerCompleted+=new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
      bw.RunWorkerAsync(); 
     } 

     private void bw_DoWork(object sender, DoWorkEventArgs e) 
     { 

      FlowDocument myFlowDocument = new FlowDocument(); 
      Paragraph myParagraph = new Paragraph(); 
      myParagraph.Inlines.Add(new Bold(new Run("Some bold text in the paragraph."))); 
      myFlowDocument.Blocks.Add(myParagraph); 

      e.Result = myFlowDocument; 

     } 

     private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      //runtime error occured here. 
      fviewer.Document = (FlowDocument)e.Result; 
     } 

    } 
} 

私は別のスレッドでWPFオブジェクトにアクセスすると聞いて、私はディスパッチャ()を使用する必要があります。 しかし、RunWorkerCompleted()はUIの別のスレッドではないので、私は混乱しています。 myFlowDocumentにはどのようにアクセスできますか?

答えて

2

問題は、FlowDocumentがUIスレッドとは異なるスレッドで作成されるためです。

メインUIスレッドでフロードキュメントを作成する必要があります。バックグラウンドワーカーでは、フロードキュメントDispatcher.Invokeを使用してプロパティを設定し、アイテムを作成する必要があります。あなたの単純な例では、バックグラウンドワーカーを使用することに本当の利点はありません。作業者は、長時間実行されているプロセスの処理に使用する必要があります。

唯一の方法は、バックグラウンドワーカーでドキュメントを作成し、インメモリストリームにシリアル化し、UIスレッドに戻った後に逆シリアル化することです。

0

Bob Valeが正しく指摘しているように、別のスレッドでUIオブジェクトを決して作成しないことが一般的な経験則です。プレゼンテーションオブジェクトを作成するとき。 UIスレッドでそれを行う必要があります。バックグラウンドタスクは単純なデータを返さなければなりません。私はこのように見えるDoWorkを変更したい:この場合

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     Action<string> action = r => 
     { 
      FlowDocument myFlowDocument = new FlowDocument(); 
      Paragraph myParagraph = new Paragraph(); 
      myParagraph.Inlines.Add(new Bold(new Run(r))); 
      myFlowDocument.Blocks.Add(myParagraph); 
      fviewer.Document = myFlowDocument; 
     }; 
     Dispatcher.Invoke(action, (string)e.Result); 
    } 

、何Dispatcherがやっているが、あなたがスケジュールすることができている:

private void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     //Assume some kind of "work" is being done here. 
     e.Result = "Some bold text in the paragraph"; 
    } 

は次に、ドキュメントのコンテンツのDispatcher経由で設定することができますUIを所有するスレッドに対して作業(この場合は代理人)を行います。

+0

しかし、fviewerとフロードキュメントは別々のスレッドで作成されているため、それらを組み合わせることはできません。 –

+0

コードが機能しませんでした。同じ例外が発生しました。ありがとう。 – mjk6026

+0

@Bob - 確かに。ナイスキャッチ。私は私の答えを更新しました。 – vcsjones

0

私はそれをしないでくださいSystem.ComponentMode.BackgroundWorker

のDoWorkから

、 'FlowDocument'、WPFオブジェクトを作りました。 UIオブジェクトからUIオブジェクトを作成して更新する必要があります。

関連する問題