C#:将对象添加到队列时触发事件

每当将对象添加到Queue时,我都需要能够触发事件。

我创建了一个扩展Queue的新类:

 public delegate void ChangedEventHandler(object sender, EventArgs e); public class QueueWithChange : Queue { public event ChangedEventHandler Changed; protected virtual void OnChanged(EventArgs e) { if (Changed != null) { Changed(this, e); } } } 

然后从另一个类附加事件,如:

 QueueWithChange eventQueue = new QueueWithChange(); // 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)eventQueue.Enqueue(something) )时,附加事件就不会被触发。

我在这里想念的是什么?

如果您指的是非通用的Queue类,那么您可以覆盖Enqueue

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

但是,如果您指的是通用的Queue类,请注意没有合适的虚拟方法可以覆盖。 您可能最好用自己的类封装队列:

(**重要编辑:删除基类!!! **)

 class Foo { private readonly Queue queue = new Queue(); 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; } } 

但是,看看你的代码,你可能在这里使用多个线程。 如果是这种情况,请考虑使用线程队列 。

我刚刚写了我称之为TriggeredQueue的内容。 它启发了Marc Gravell的答案。

你可以在这里找到我的post: http : //joesauve.com/triggeredqueuet

这里的要点是: http : //gist.github.com/jsauve/b2e8496172fdabd370c4

它有四个事件:

  • WillEnqueue
  • WillDequeue
  • DidEnqueue
  • DidDequeue

你可以像这样挂钩任何这些:

 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 }; 

一个巧妙的技巧是你可以使用DidDequeue方法启动一些进程,通过发出Web请求或从文件系统加载一些数据来确保队列已满。我在Xamarin移动应用程序中使用此类来确保数据和图像是预先缓存的,以提供流畅的用户体验,而不是在图像滚动到屏幕后加载图像(就像你可能在Facebook和无数其他应用程序中看到的那样)。

尝试

 public new void Enqueue(Delegate d) { base.Enqueue(d); OnChanged(EventArgs.Empty); } 

你必须重写Enqueue,才能调用OnChanged。