19

オブジェクトが に追加されるたびにイベントをトリガーできるようにする必要がありますQueue<Delegate>

拡張する新しいクラスを作成しましたQueue

public delegate void ChangedEventHandler(object sender, EventArgs e);

public class QueueWithChange<Delegate> : Queue<Delegate>
{
    public event ChangedEventHandler Changed;

    protected virtual void OnChanged(EventArgs e) {
        if (Changed != null)
        {
            Changed(this, e);
        }
    }
}

そして、次のように、別のクラスからイベントを添付します。

QueueWithChange<TimerDelegate> eventQueue = new QueueWithChange<TimerDelegate>();

//

eventQueue.Changed += new ChangedEventHandler(delegate(object s, EventArgs ex) {
    //This event is not being triggered, so this code is unreachable atm...and that is my problem

    if (eventQueue.Count > 0)
    {
        eventQueue.Dequeue().Invoke(new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(5) });
        actionTimer.Stop();
    }
});

しかし、オブジェクト ( ) をキューに入れるたびにeventQueue.Enqueue(something)、添付イベントが発生しません。

ここで何が欠けていますか?

4

4 に答える 4

35

非ジェネリックQueueクラスを意味する場合は、次のようにオーバーライドできますEnqueue

public override void Enqueue(object obj)
{
    base.Enqueue(obj);
    OnChanged(EventArgs.Empty);
}

ただし、ジェネリックQueue<T>クラスを意味する場合は、オーバーライドする適切な仮想メソッドがないことに注意してください。独自のクラスでキューをカプセル化することをお勧めします。

(** 重要な編集: 基本クラスを削除!!! **)

class Foo<T>
{
    private readonly Queue<T> queue = new Queue<T>();
    public event EventHandler Changed;
    protected virtual void OnChanged()
    {
        if (Changed != null) Changed(this, EventArgs.Empty);
    }
    public virtual void Enqueue(T item)
    {
        queue.Enqueue(item);
        OnChanged();
    }
    public int Count { get { return queue.Count; } }

    public virtual T Dequeue()
    {
        T item = queue.Dequeue();
        OnChanged();
        return item;        
    }
}

ただし、コードを見ると、ここで複数のスレッドを使用している可能性があります。その場合は、代わりにスレッド化されたキューを検討してください。

于 2009-02-10T08:15:03.120 に答える
6

私が TriggeredQueue と呼んでいるものについて書きました。Marc Gravell の回答に触発されました。

ここで私の投稿を見つけることができます: http://joesauve.com/triggeredqueuet

ここの要点: http://gist.github.com/jsauve/b2e8496172fdabd370c4

次の 4 つのイベントがあります。

  • キューに入れる
  • ウィルデキュー
  • キューに入れました
  • ディキュー

次のように、これらのいずれかにフックできます。

YourQueue.WillEnqueue += (sender, e) => {
    // kick off some process
};
YourQueue.DidEnqueue += (sender, e) => {
    // kick off some process
    // e.Item provides access to the enqueued item, if you like
};
YourQueue.WillDequeue += (sender, e) => {
    // kick off some process
};
YourQueue.DidDequeue += (sender, e) => {
    // kick off some process
    // e.Item provides access to the dequeued item, if you like
};

巧妙なトリックの 1 つは、DidDequeue メソッドを使用してプロセスを開始し、Web 要求を作成したり、ファイルシステムからデータをロードしたりしてキューがいっぱいになるようにすることです。私は Xamarin モバイル アプリでこのクラスを使用して、データがまた、スムーズなユーザー エクスペリエンスを提供するために、画像が画面にスクロールされた後に読み込まれるのではなく、画像が事前にキャッシュされます (Facebook やその他の無数のアプリで見られるように)。

于 2014-05-09T20:27:22.747 に答える
1

試す

public new void Enqueue(Delegate d)
{
    base.Enqueue(d);
    OnChanged(EventArgs.Empty);
}
于 2009-02-10T08:16:55.910 に答える
0

OnChanged を呼び出すには、Enqueue をオーバーライドする必要があります。

于 2009-02-10T08:11:03.600 に答える