8


0

非同期でイベントを発生させる

私は、そのイベントを多くの購読者が持っているコンポーネントで非同期イベントのディスパッチをするためのオプションを調べています。 オプションを熟読する際に、この例に遭遇しました。

public event ValueChangedEvent ValueChanged;
public void FireEventAsync(EventArgs e)
{
    Delegate[] delegates = ValueChanged.GetInvocationList();
    foreach (Delegate d in delegates)
    {
        ValueChangedEvent ev = (ValueChangedEvent)d;
        ev.BeginInvoke(e, null, null);
    }
}

古い構文(サンプルは.NET 1.1からのもの)を超えて、これは深刻なリソースリークであるように私には見えます。 完了メソッド、完了のためのポーリング、または `+ EndInvoke +`が呼び出される他の方法はありません。

私の理解では、すべての「+ BeginInvoke 」は対応する「 EndInvoke 」を持っている必要があります。 そうでない場合、非同期イベント中に発生した(潜在的に)例外とともに、保留中の ` AsyncResult +`オブジェクトインスタンスが浮かんでいます。

コールバックを提供し、 `+ EndInvoke +`を実行することでそれを変更するのは簡単ですが、必要がない場合は、 . .

非同期実行を処理することは完全に別の問題であり、そしてUIスレッドと同期する必要性と組み合わされている。 `+ InvokeRequired +`など)は、これらの非同期通知を行うという考え全体を非常にうまく活用できます。

それで、2つの質問:

  1. すべての + BeginInvoke +`には 対応する `+ EndInvoke +

  2. 上記で述べたこと以外に、行うべき他の落とし穴があります Windows Formsアプリケーションの非同期イベント通知?

3 Answer


3


`+ BeginInvoke()`の呼び出しは、 ` EndInvoke()`とペアにする必要がありますが、実行しないとリソースリークは発生しません。 ` BeginInvoke()`によって返される ` IAsyncResult +`はガベージコレクションされます。

このコードの最大の落とし穴は、アプリケーションを終了させる例外に非常にさらされていることです。 デリゲートの呼び出しを例外ハンドラでラップし、発生した例外をどのように伝播させるかを考えることができます(最初のものを報告し、集約例外を生成するなど)。

`+ BeginInvoke()`を使用して削除を呼び出すと、スレッドのスレッドキューからイベントが実行されます。 これは、イベントが常にメインUIスレッドから発生することを意味します。 これはいくつかのイベントハンドラシナリオを扱うことを難しくするかもしれません(例えば。 UIを更新します。 ハンドラーは、プライマリUIスレッドと同期するために ` SynchronizationContext.Send()`または ` .Post()+`を呼び出す必要があることを認識する必要があります。 もちろん、他のすべてのマルチスレッドプログラミングの落とし穴も当てはまります。


1


しばらく考えてみたところ、Windowsフォームコントロールで非同期イベントを実行するのはおそらく悪い考えであるという結論に至りました。 WindowsフォームイベントはUIスレッドで発生するはずです。 そうしないと、クライアントに過度の負担がかかり、 `+ AsyncResult +`オブジェクトと非同期例外が混乱する可能性があります。

クライアントが(+ BackgroundWorker +やその他の手法を使用して)独自の非同期処理を開始するか、イベントを同期的に処理する方が簡単です。

もちろん例外があります。 たとえば、 `+ System.Timers.Timer `は、スレッドプールスレッドで ` Elapsed +`イベントを発生させます。 しかし、その後、最初の通知はプールスレッドに届きます。 それは一般的な規則のように見えます:最初の通知を受けたのと同じスレッドでイベントを発生させる。 少なくとも、それが私にとって最適なルールです。 そのようにして、オブジェクトの漏洩について疑いはありません。


0


  1. いいえ EndInvokeは、戻り型が指定されている場合にのみ必要です。 これをチェックしてください:http://social.msdn.microsoft.com/Forums/en-US/clr/thread/b18b0a27-e2fd-445a-bcb3-22a315cd6f0d / [スレッド]。 また、私はこの threadを投稿しました。

  2. 私は本当にそれを手に入れることができません! :-) ごめんなさい。