2009-05-21 6 views
2

.NET(C#)のイベントに関する質問があります。私はバックグラウンドタスクを実行しているいくつかの状況でコードを書く必要がありました。タスクが完了したか、ファイルのコピーが完了したなど、何かが発生したことをメインスレッドまたはコントローラクラスに通知したいのですが、バックグラウンドタスクがメインスレッドのデリゲートがイベントを処理するのを待つようにします。イベントリスナーの実行を待たずにイベントを発生させるにはどうすればよいですか?

私はメッセージの受け渡しのようなことをしたい:メッセージを送信するが、誰がそれをどうするか気にする。例えば

クラスは、配列中のいくつかのプロセス、次々に処理するように書かれています。各プロセスは、バックグラウンドスレッドで実行する必要があります。作業が完了すると、イベントが発生し、コントローラに完了したことが通知されます(OnCompleted()メソッドを使用して)。

問題は、コントローラのイベントハンドラを使用して後続のプロセスを開始すると、メソッドは、すべてのプロセスが完了するまでコールスタックに留まります(実行を終了することはありません)。

この状況では、バックグラウンドタスクは、イベントを発生させるメソッドをスタックに保持せずに、作業が完了したことをコントローラクラスにどのように通知できますか?

例2:バックアッププログラム。

バックグラウンドスレッドが実行され、各ファイルがコピー先にコピーされます。バックグラウンドはに通知します。最後にコピーされたファイルがUIに通知されますが、UIが更新されるのを待つ必要はありません。代わりに、ちょうど「BTW、ここにいくつかの情報があります。さて、私は仕事に戻ろう」と言いたいと思います。イベントリスナーは、イベントライザーの処理をブロックすべきではありません。

答えて

2

あなたはイベントを上げたときに(述べたように)非同期呼び出しを行う、あるいは単にバックグラウンドスレッドでイベント自体を上げることができる:

void OnUpdated(EventArgs e) { 
    EventHandler h = this.Updated; 
    if (h != null) h(e); 
} 

void DoStuff() { 
    BigMethod(); 
    ThreadPool.QueueUserWorkItem(OnUpdated, EventArgs.Empty); 
    BigMethod2(); 
} 

あなたが非同期的に上げる場合は、複数のリスナーがあなたを処理することになります同時にイベントが発生します。少なくともスレッドセーフなEventArgクラスが必要です。それらがあなたのクラスとやりとりすることを期待するならば、非常に慎重に文書化するか、スレッドセーフにしてください。

バックグラウンドスレッドでイベントを発生させることは、クラスメソッドに対して同じ注意事項を示しますが、EventArgsクラス自体について心配する必要はありません。

1

最初のイベントは何も行いませんが、それ以外のイベントリスナーはありません。

+0

のコーディングを示していますか? –

+0

さて、あなたは別のスレッドをキックオフする方法を知っているようです。最初のイベントリスナーにこれを実行させてください(イベントを使用してオブジェクトを作成するとすぐに、BeginInvoke/EndInvokeパターンについては –

3

イベントの呼び出しリストでデリゲートを非同期に呼び出そうとしているようです。

私はあなたが.NET Asynchronous Events To Send Process Status To User Interfaceを読むことをお勧めします:

を.NET Frameworkは、私たちに非同期的に私たちのクラスでのイベント(および他の の項目を)上げの 概念を提供しています。 これは、我々がそのイベントに 加入者(通常は ユーザーインターフェース)が イベントを発生させた方法で 処理を保持していないような方法でイベント に上げることができることを意味します。そのメリットは は、 メソッドの パフォーマンスに悪影響を与えません。

+0

ハンドラを割り当てましたが、リスナー側ではなくリスナー側で使用することを考えていました 未処理のBeginInvokeコールが大量にあった場合に問題が発生する可能性がありますか? –

0

ケース2のバックアッププログラムの場合。コードサンプルはファイルコピーを非同期的に起動し、コピーが完了するとコールバックメソッドを呼び出します。

:あなたはUIを更新するのを待つたくない場合は、コールバックでは、あなたは非同期

あなたはあなたのようにそれを呼び出すことができ、非同期の代表

public class AsyncFileCopier 
    { 
     public delegate void FileCopyDelegate(string sourceFile, string destFile); 

     public static void AsynFileCopy(string sourceFile, string destFile) 
     { 
      FileCopyDelegate del = new FileCopyDelegate(FileCopy); 
      IAsyncResult result = del.BeginInvoke(sourceFile, destFile, CallBackAfterFileCopied, null); 
     } 

     public static void FileCopy(string sourceFile, string destFile) 
     { 
      // Code to copy the file 
     } 

     public static void CallBackAfterFileCopied(IAsyncResult result) 
     { 
      // Notify UI by calling an async del (probably using fire & forget approach or another callback if desired) 
     } 
    } 

を使用することができますUI更新コードを呼び出す必要があります

AsyncFileCopier.AsynFileCopy("abc.txt", "xyz.txt"); 

このlinkは、私はC#でいることだろうどのようASYNの異なる技術が

関連する問題