非同期コールバックのマルチスレッド環境で、イベントハンドラを適切に追加/削除する方法について質問があります。マルチスレッドアプリケーションのイベントハンドラの追加と削除
私は、非管理コードからコールバックを送出するProxyDLLからの非同期コールバックを受け取るMyCoreクラスを持っています。私はイベントを購読するフォームを持っています。
イベントの着脱にはどのようなアプローチが適していますか。私はMulticastDelegateが_invocationcountを持っていることに気づいた。それは何ですか?コールバックが完了するまでコールバックコールが処理中の場合、イベントの内部ロジックはイベントから切り離されますか?その子犬のために_invocationcountが存在しますか? イベントからの脱落は(一般的に)トレッドセーフですか?
class Form1
{
EventHandler m_OnResponse;
Int32 m_SomeValue;
Form1()
{
m_OnResponse = new EventHandler(OnResponseImpl);
m_MyCore.SetCallBackOnLogOn(m_OnResponse);
}
~Form1()
{
m_MyCore.ReleaseCallBackOnLogOn(m_OnResponse);
}
private OnResponseImpl(object sender, EventArgs e)
{
Thread.Sleep(60*1000);
m_SomeValue = 1; // <<-- How to/Who guarantees that Form1 obj is still
// alive. May be callback was invoked earlier and
// we just slept too long
if (!this.IsDisposed)
{
invokeOnFormThread(DoOnResponseImpl, sender, e);
}
}
}
class MyCore
{
private event EventHandler OnLogOn;
public void SetCallBackOnLogOn(EventHandler fn)
{
// lock (OnLogOn)
{
OnLogOn += fn;
}
}
ReleaseCallBackOnLogOn(EventHandler fn)
{
// lock (OnLogOn)
{
OnLogOn -= fn;
}
}
public void DoDispatchOnLogOn()
{
// lock (OnLogOn)
{
if (OnLogOn != null)
{
OnLogOn(this, null);
}
}
}
}
ありがとうございます!それは良い点です。そして、安全性に関して - イベントからのリスナーの登録を解除することがブロッキングコールであると言いたいのですか? – adspx5
@ adspx5:C#4.0以上では、Interlocked.CompareExchangeを使用してサブスクライブとサブスクライブを行います。 C#3.0以下では 'lock(this)'を使用します。したがって、現在ロックが他の誰かによって保持されている場合は、C#3.0以下がブロックされます。 –
それは私が理解しようとしているものではありません。私は理解しましたが、呼び出しリストの変更については心配しないでください。私は代議員の生涯について心配しています。 ReleaseCallBackOnLogOnがサブスクライブ解除のデリゲートを終了したときにコールバックが呼び出されないようにする必要があります。私の代理人が10秒間スリープ状態になり、その後、MyForm :: m_Somevalueを変更したとします。コールバックの呼び出しが完全に完了するまで、クラスインスタンスがまだ生存していることを確認する必要があります。 – adspx5