我在ManualResetEvent和积压的事件中遇到了一些问题。我的应用程序正在订阅消息,然后运行一个很长的任务。
我的问题是,我收到的消息太多,我无法处理。任务大约需要5秒来处理,但我每2-3秒就会收到一条新消息。
理想情况下,我想要做的是忽略任何新事件,直到我完成任务处理,然后再次开始“侦听”。目前,我似乎正在按照接收和处理的顺序积压事件。正如您可以想象的那样,几个小时后,正在处理的消息非常旧。
我不能从多个线程运行长时间运行的任务。
也许我需要某种队列机制,然后清除最后一条消息(Last On First Off)并删除队列?
有什么想法吗?
我还会在长时间运行的进程结束时调用ManualResetEvent.Set() --根据我的研究,这是正确的吗?我是否应该在长时间运行的任务开始时重置(),使线程阻塞,然后在结束时设置()?
发布于 2013-11-20 00:10:58
创建一个循环缓冲区,将其视为后进先出队列(堆栈)。因此,假设您希望队列中最多有10个条目:
const int MaxItems = 10;
Item[] theQueue = new Item[];
int insertPoint = 0;
object myLock = new object();
// initialize the array to all NULL.
void Enqueue(Item t)
{
lock (myLock)
{
theQueue[insertPoint] = t;
insertPoint = (insertPoint+1) % 10;
}
}
Item Dequeue()
{
lock (myLock)
{
int takeFrom = insertPoint-1;
if (takeFrom < 0)
takeFrom = MaxItems-1;
if (theQueue[takeFrom] != null)
{
var rslt = theQueue[takeFrom];
insertPoint = takeFrom;
return rslt;
}
// queue is empty. Either return null or throw an exception.
return null;
}
}当然,您会希望将所有这些都包装到一个漂亮的对象中。但这是基本的想法。
发布于 2013-11-19 22:41:14
这个怎么样:
在任何给定时间,您都有一条消息正在处理,还有一条消息在等待处理。
当您收到新消息时,您将覆盖等待处理的消息。
您的处理线程将等待,直到有消息等待处理,然后将其标记为正在处理,处理它,然后再次启动。
添加一些同步逻辑,您将获得以下代码:
private object _sync = new object();
private Message _beingProcessed;
private Message _waitingToBeProcesssed;
public void OnMessageReceived(Message message)
{
lock(sync)
{
_waitingToBeProcesssed = message;
Monitor.Pulse(sync);
}
}
public void DoWork()
{
while (true)
{
lock (sync)
{
while (_waitingToBeProcesssed == null)
{
Monitor.Wait(sync);
}
_beingProcessed = _waitingToBeProcesssed;
_waitingToBeProcesssed = null;
}
Process(_beingProcessed); //Do the actual work
}
}https://stackoverflow.com/questions/20071506
复制相似问题