我遇到了一些围绕ManualResetEvent和积压事件的问题。我的应用程序正在订阅消息,然后运行一项长任务。
我遇到的问题是我收到的消息多于我可以处理的消息。任务需要大约5秒才能处理,但我每2-3秒收到一条新消息。
理想情况下,我想要做的是忽略任何新事件,直到我完成处理任务然后再次开始'聆听'。目前,我似乎按照接收和处理的顺序对事件进行了积压。您可以想象,几个小时后,正在处理的消息非常陈旧。
我无法从多个线程运行长时间运行的任务。
也许我需要某种排队机制然后清除最后一条消息(Last On First Off)并删除队列?
有什么想法吗?
我还在长时间运行的过程结束时调用ManualResetEvent.Set() - 从我的研究中我明白这是正确的吗?我应该在长时间运行的任务开始时重置()以导致线程阻塞然后在结束时设置()?
答案 0 :(得分:1)
创建一个循环缓冲区,将其视为LIFO队列(堆栈)。所以,假设您希望队列中最多有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;
}
}
当然,你想把它们全部包装成一个漂亮的物体。但那是基本的想法。
答案 1 :(得分:0)
这个怎么样:
在任何给定时间,您都会处理一条消息,并等待处理一条消息。
收到新邮件时,会覆盖等待处理的邮件。
您的处理线程会等到有消息等待处理,然后将其标记为正在处理,处理它,然后重新开始。
添加一些同步逻辑,您将获得以下代码:
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
}
}