私には、これは古典的なパブリッシャー/リスナーの問題のように思えます。
私なら、interface:IMyClassNameEventListener
を作成し、MyClass
そのインスタンスをコンストラクターのパラメーターとして取得します。次に、コンストラクターでAttach(MyClass obj)
インターフェイス インスタンスのメソッドを呼び出します。もちろん、リスナーにはシングルトンのライフサイクルがあり、静的である必要はありません。
少し良いアプローチは、ファクトリを使用してインスタンスを作成し、そのインスタンスをMyClass
アタッチすることです。そのため、Attach
呼び出しと依存関係はコンストラクタの外にあります。
アプリが失敗するかどうかは、リスナーの起動方法に依存します。クラスを調べると、TaskFactory
例外の伝播を処理するオプションが提供されます。リスナーが失敗した場合にアプリをどのように動作させたいですか?
もちろん、リスナー オブジェクト自体では、何か処理する必要がある場合にのみコードを実行する必要があります。したがって、イベントを受け取ると、スレッドを開始します。スレッドを 1 つだけ実行したい場合は、アクションのキューを使用できます。
リスナー クラス内では、次のようなものが必要になる場合があります。
private Queue<Action> ActionQueue = new Queue<Action>();
private object LockObj = new Object();
private volatile bool IsRunning;
public void Attach(Class1 obj)
{
obj.SomeEvent += this.HandleEvent;
}
private void HandleEvent(object sender, EventArgs e)
{
lock(this.LockObj)
{
this.ActionQueue.Enque(() => this.Handle(sender, e));
if (!this.IsRunning)
{
Task.Factory.StartNew(() => this.Loop() );
}
}
}
private void Loop()
{
this.IsRunning = true;
while ((Action action = this.DequeueAction()) != null)
action();
this.IsRunning = false;
}
private Action DequeueAction()
{
lock (this.LockObj)
{
return this.ActionQueue.Count > 0 ? this.ActionQueue.Dequeue() : null;
}
}
private void Handle(object sender, EventArgs e)
{
//handling code
}