Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#:将对象添加到队列时触发事件_C#_Events_Delegates_Queue - Fatal编程技术网

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,您删除基类的原因是什么?这是一个错误!我打算使用组合,而不是继承-因为我们已经观察到继承不能提供我们所需要的…@adoppilot
while(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
};