从多个线程获取消息到队列并让一个单独的线程一次处理该队列的项目的最佳方法是什么?
在尝试从多个线程断开活动时,我经常使用这种模式。
我为此使用了 BlockingCollection,如下面的代码摘录所示:
// start this task in a static constructor
Task.Factory.StartNew(() => ProcessMultiUseQueueEntries(), TaskCreationOptions.LongRunning);
private static BlockingCollection<Tuple<XClientMsgExt, BOInfo, string, BOStatus>> _q = new BlockingCollection<Tuple<XClientMsgExt, BOInfo, string, BOStatus>>();
/// <summary>
/// queued - Simple mechanism that will log the fact that this user is sending an xMsg (FROM a user)
/// </summary>
public static void LogXMsgFromUser(XClientMsgExt xMsg)
{
_q.Add(new Tuple<XClientMsgExt, BOInfo, string, BOStatus>(xMsg, null, "", BOStatus.Ignore));
}
/// <summary>
/// queued - Simple mechanism that will log the data being executed by this user
/// </summary>
public static void LogBOToUser(BOInfo boInfo)
{
_q.Add(new Tuple<XClientMsgExt, BOInfo, string, BOStatus>(null, boInfo, "", BOStatus.Ignore));
}
/// <summary>
/// queued - Simple mechanism that will log the status of the BO being executed by this user (causes the red square to flash)
/// </summary>
public static void LogBOStatus(string UserID, BOStatus status)
{
_q.Add(new Tuple<XClientMsgExt, BOInfo, string, BOStatus>(null, null, UserID, status));
}
/// <summary>
/// An endless thread that will keep checking the Queue for new entrants.
/// NOTE - no error handling since this can't fail... :) lol etc
/// </summary>
private static void ProcessMultiUseQueueEntries()
{
while (true) // eternal loop
{
Tuple<XClientMsgExt, BOInfo, string, BOStatus> tuple = _q.Take();
// Do stuff
}
}
这很好用——所以我想——直到 VS2010 中的性能向导开始突出显示_q.Take()行作为我代码中的最高争用行!
注意我还使用了标准的 ConcurrentQueue 和 ManualResetEvent 组合,每次我将一个项目插入队列时,我都会发出 resetevent 信号,允许工作线程检查和处理队列,但这也具有在 . WaitOne() 方法...
是否有其他方法可以解决这种让许多线程将对象添加到并发队列中的常见模式 - 并且让一个线程在其自己的时间一次一个地遍历项目......
谢谢!!