2012-01-09 6 views
3

私はWPFアプリケーションで作業しています。私はBackgroundWorker経由で非同期で実行したいという時間がかかる方法があります。メソッドが実行されている間、私はモーダルの "Please Wait ..."ダイアログウィンドウを表示します。BackgroundWorkerが完了すると自動的に閉じなければなりません。STA/MTAの問題を起こすことなく、BackgroundWorkerが動作している間にモーダルウィンドウを表示

私は現在BackgroundWorkerやマルチスレッドプログラミングの経験がほとんどありません。

以下のコードは、InvalidOperationExceptionというメッセージで表示され、というメッセージが表示されます。「多くのUIコンポーネントにはこれが必要なため、呼び出しスレッドはSTAでなければなりません。

私が達成しようとしていることを達成する方法と、何がうまくいかないのか理解するのを助けることができる場合、追加のブラウニーポイントを教えてください。

多くの感謝!ただ、明確にする

EDIT - アイデアは、メインスレッドがモーダルダイアログを示し、その後、BackgroundWorkerを起動していることです。作業者が完了すると、モーダルダイアログが閉じます。モーダルダイアログが閉じると、メインスレッドが続行されます。

public class ImageResizer 
{ 
    private BackgroundWorker worker; 
    private MemoryStream ImageData { get; set; } // incoming data 
    private public MemoryStream ResizedImageData { get; private set; } // resulting data 
    private Dialogs.WorkInProgressDialog ProgressDialog; 


    // Public interface, called by using class: 
    public MemoryStream ReduceImageSize(MemoryStream imageData) 
    { 
     // injected data: 
     this.ImageData = imageData; 

     // init progress dialog window: 
     ProgressDialog = new Dialogs.WorkInProgressDialog(); 

     // Start background worker that asyncronously does work 
     worker = new BackgroundWorker(); 
     worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
     worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);    
     worker.RunWorkerAsync(); 

     // Show progress dialog. Dialog is MODAL, and must only be closed when resizing is complete 
     ProgressDialog.ShowDialog(); // THIS LINE CAUSES THE INVALID OPERATION EXCEPTION 

     // This thread will only continue when ProgressDialog is closed. 

     // Return result 
     return ResizedImageData; 
    } 

    private void worker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     // Call time consuming method 
     ResizedImageData = ReduceImageSize_ActualWork(); 
    } 

    // The actual work method, called by worker_DoWork 
    private MemoryStream ReduceImageSize_ActualWork() 
    { 
     // Lots of code that resizes this.ImageData and assigns it to this.ResizedImageData 
    } 

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     // Async work completed - close progress dialog 
     ProgressDialog.Close(); 
    } 
} 
+0

モデレーター、私の質問を削除してください - 私が受け取ったエラーは無関係なコーディングエラーのためでした。したがってこの質問はA)ナンセンスとB)誰にも役に立たないです。ありがとう。 –

答えて

2

ShowDialogをBackgroundWorkerから呼び出すことはできません。あなたはそれを実行するためにUIスレッドを依頼するディスパッチャを使用する必要があります。

this.Dispatcher.BeginInvoke(new Action(() => ProgressDialog.ShowDialog())); 

のBackgroundWorkerの「完了」イベントがUIスレッドで実行されるので、この部分は問題ないはずです。

+1

また、UIスレッドはDispatcher.Invokeを使用してShowDialog()を処理するため、RunWorkerCompletedのProgressDialog.Close()は必要であるか、または合法ですか? – Sabuncu

+0

あなたは完全に正しいです。私はサンプルのコメントを誤解し、何らかの形で、モーダルが閉じられた後にのみコードを継続しなければならないと考えました。 BeginInvokeで置き換えます。バックグラウンドワーカーが作業を終えた時点でモーダルダイアログが開いているので、Closeは便利で合法です。 –

+0

ありがとう@KooKiz、私は混乱しています - 私が提供したコードでは、私はBackgroundWorkerからShowDialogを呼び出すのではなく、 'worker.RunWorkerAsync();'と 'ProgressDialog.ShowDialog();'同じ方法。 –

関連する問題