次のコードでは、2つのクラスがあります。1つは別のスレッドで実行されてイベントを発生させ、もう1つはこのイベントをサブスクライブしてイベントからデータを受信します。JonSkeetの記事http://csharpindepth.com/Articles/Chapter2/Events.aspxに基づいたイベントコード
この記事ではhttp://www.codeproject.com/Articles/37474/Threadsafe-それが言うイベント...
このため、JonSkeetがDelegatesandEventsの最後に推奨するのと同じアプローチをお勧めします。「それをしないでください」、つまり、マルチスレッド方式でイベントを使用しないでください。オブジェクトにイベントが存在する場合、そのイベントをサブスクライブまたはサブスクライブ解除できるスレッドは1つだけであり、イベントを発生させるのは同じスレッドです。
これで明らかに私のデザインはそれを破り、サブスクライブされたスレッドとは異なるスレッドでイベントを発生させます。マルチスレッド方式でイベントを使用しないという原則に準拠するように設計を変更するにはどうすればよいですか、またはこれは不可能ですか?
私がそれを行うことを考えたもう1つの方法は、コールバックメソッドをデリゲートとしてクラスBに渡し、イベントを呼び出す代わりにそれを呼び出すことでしたか?
スティックの端が完全に間違っている可能性があるので、説明をいただければ幸いです。
注:.Net 4.0でこの問題が明らかに解決されたことは承知していますが、.Net4より前にそれを行う方法があるかどうかについては引き続き関心があります。
public delegate void MyDelegate(int a);
class A
{
void main()
{
B bObject = new B();
bObject.MyEvent += new MyDelegate(NiceMethod);
bObject.Run();
}
void NiceMethod(int a)
{
Console.Writeline({0}, a);
}
}
class B
{
readonly object eventLock = new object();
MyDelegate myDel;
public event MyDelegate MyEvent
{
add
{
lock (eventLock)
{
myDel += value;
}
}
remove
{
lock (eventLock)
{
myDel -= value;
}
}
}
//Assume this runs in a new thread and calls back data using MyEvent
//Have ommited thread code for simplicity
public void Run()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
MyDelegate handler;
lock (someEventLock)
{
handler = myDel;
}
if (handler != null)
{
handler (i);
}
}
}
}