C#:将对象添加到队列时触发事件
每当将对象添加到C#:将对象添加到队列时触发事件,c#,events,delegates,queue,C#,Events,Delegates,Queue,每当将对象添加到队列时,我需要能够触发事件 我创建了一个扩展队列的新类: public delegate void ChangedEventHandler(object sender, EventArgs e); public class QueueWithChange<Delegate> : Queue<Delegate> { public event ChangedEventHandler Changed; protected virtual vo
队列时,我需要能够触发事件
我创建了一个扩展队列的新类:
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);
}
}
}
public委托void changedventhadler(对象发送方,事件参数e);
公共类QueueWithChange:Queue
{
公共事件变更事件处理者变更;
受保护的虚拟void一旦更改(EventArgs e){
如果(已更改!=null)
{
改变(本,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();
}
});
QueueWithChange eventQueue=new QueueWithChange();
//
eventQueue.Changed+=新的ChangedEventHandler(委托(对象s,EventArgs ex){
//这个事件没有被触发,所以这个代码是无法访问的atm…这就是我的问题
如果(eventQueue.Count>0)
{
eventQueue.Dequeue().Invoke(新的dispatchermer(){Interval=TimeSpan.frommilluses(5)});
actionTimer.Stop();
}
});
但是每当我将一个对象排入队列(eventQueue.enqueue(something)
)时,附加的事件不会被触发
我在这里遗漏了什么?您必须重写Enqueue,以便在更改后调用。如果您指的是非通用的队列
类,那么您可以重写Enqueue
:
public override void Enqueue(object obj)
{
base.Enqueue(obj);
OnChanged(EventArgs.Empty);
}
但是,如果您指的是泛型队列
类,那么请注意,没有合适的虚拟方法可以覆盖。您最好使用自己的类来封装队列:
(**重要编辑:删除基类!!!**)
class-Foo
{
私有只读队列队列=新队列();
公共事件事件处理程序已更改;
受保护的虚拟void OnChanged()
{
if(Changed!=null)Changed(this,EventArgs.Empty);
}
公共虚拟空位排队(T项)
{
排队。排队(项目);
OnChanged();
}
公共整数计数{get{return queue.Count;}}
公共虚拟T出列()
{
T item=queue.Dequeue();
OnChanged();
退货项目;
}
}
但是,看看您的代码,这里似乎可能使用了多个线程。如果是这样的话,请考虑A。 尝试
public new void Enqueue(Delegate d)
{
base.Enqueue(d);
OnChanged(EventArgs.Empty);
}
我只是写了一篇我称之为TriggeredQueue的文章。这是马克·格雷威尔的答案
你可以在这里找到我的帖子:
要点如下:
它有四个活动:
- 威伦队列
- 将退出队列
- 排队
- 不排队
您可以像这样连接到任何一个:
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和无数其他应用程序中看到的那样)。重新声明/method隐藏是脆弱的、非多态的、脆弱的;调用者只需进行一次强制转换就可以跳过代码。Enqueue在通用QueueRight上不是虚拟的,这太可惜了。我想你必须创建一个IQueue接口,然后有自己的实现;这正是我想要的。谢谢Marc的高质量回答。我还将检查您提到的线程队列。从设计原则的角度来看,使用组合优于继承(广义上讲),因此我支持您的解决方案。Marc,您删除基类的原因是什么?这是一个错误!我打算使用组合,而不是继承-因为我们已经观察到继承不能提供我们所需要的…@adoppilotwhile(Count>0)yield return Dequeue()代码>
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
};