1

私は WPF アプリケーションを持っており、特定のクラスのアプリケーションの存続期間中、イベントをリッスンして処理する必要があります。

ラッパー クラスを作成し、その静的インスタンスを作成して "StartListening()" を呼び出すのは悪い習慣ですか? この静的インスタンスで未処理の例外が発生した場合はどうなりますか? ASP.NET アプリケーションの場合のように、アプリケーション全体を破壊するのでしょうか?

QueueUserWorkItem を作成し、クラスを作成し、イベントをアタッチしてから、何らかの while(true){} ステートメントを挿入して、スレッドを維持する必要がありますか?

ベストプラクティスは何ですか?

4

1 に答える 1

1

私には、これは古典的なパブリッシャー/リスナーの問題のように思えます。

私なら、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
}
于 2013-02-10T18:46:08.703 に答える