3

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

メッセージパッシングのようなことをしたい:メッセージを送信するが、誰がそれをどうするかを気にする。

例えば:

クラスは、複数のプロセスを順番に処理するように作成されています。各プロセスはバックグラウンドスレッドで実行する必要があります。作業が完了すると、イベントが発生し、それが完了したことをコントローラーに通知します(たとえば、OnCompleted()メソッドを使用)

問題は、コントローラーのイベントハンドラーを使用して後続のプロセスを開始する場合、すべてのプロセスが完了するまで、前のプロセスのOnCompleteメソッドが呼び出しスタックにとどまる(実行が終了しない)ことです。

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

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

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

4

4 に答える 4

3

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

プロセスステータスをユーザーインターフェイスに送信するには、.NET非同期イベントを読むことをお勧めします。

.NET Frameworkは、クラス内のイベント(およびその他のアイテム)を非同期的に発生させるという概念を提供します。これは、イベントのサブスクライバー(通常はユーザーインターフェイス)がイベントを発生させたメソッドの処理を中断しないように、イベントを発生させることができることを意味します。利点は、ビジネスレイヤー方式のパフォーマンスに悪影響を与えないことです。

于 2009-05-21T00:36:30.447 に答える
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クラス自体について心配する必要はありません。

于 2009-05-21T01:01:42.690 に答える
1

最初のイベントにスレッドを開始する以外に何もさせないでください。そうすれば、他のイベントリスナーが何であるかは関係ありません。

于 2009-05-21T00:32:32.077 に答える
1

バックアッププログラムのケース2の場合。コードサンプルはファイルコピーを非同期で起動し、コピーが完了すると、コールバックメソッドを呼び出します。UIが更新されるのを待ちたくない場合は、コールバックで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)
        }
    }

あなたはそれを次のように呼ぶことができます:

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

このリンクは、asynコーディングのさまざまな手法を示しています

于 2009-05-21T08:13:47.960 に答える