c#阻塞收集和线程
Posted
技术标签:
【中文标题】c#阻塞收集和线程【英文标题】:c# Blocking Collection and Threading 【发布时间】:2017-03-13 08:54:57 【问题描述】:我是使用 Blocking Collection 和线程的新手,我想确保我遵循最佳实践。我正在使用非线程安全的第三方 API。我将同时向 API 发出多个请求,因此我需要将这些请求添加到队列中并一个接一个地处理它们。为此,我有一个阻塞集合:
BlockingCollection<myEventArgs> myTasks = new BlockingCollection<myEventArgs>();
private void myEventHandler(object sender, myEventArgs e)
myTasks.Add(e);
private void doWork()
while (myTasks.IsCompleted == false)
//Do some work here with the third party API.
var eArgs = myTasks.Take();
//Sometimes I have a background (thread safe) task to perform.
//This is submitted to the thread pool.
Task.Run(() => doSomeBackgroundWork());
有时我会执行一个线程安全的后台任务。例如,API 调用是异步的,我需要轮询第三方系统以检查任务是否完成。我不希望这会阻止 BlockingCollection 处理下一个任务,所以我将它提交给线程池。一旦线程池任务完成,它将触发一个事件,该事件将一个新任务添加到 BlockingCollection。
此解决方案是否合适?是否有任何问题?我是否正确假设处理 BlockingCollection 中项目的 doWork 方法将始终在同一个线程中运行?而当我从线程池触发事件时,只有事件会在线程池上运行,而不是后续的doWork方法?
【问题讨论】:
我认为 DoWork() 需要一个循环,在它内部或周围。 是的,对不起,有一个循环,我只是解释了我的代码!为了清楚起见,我现在将其添加。 旁注,标准 C# 实践要求方法和类型使用 PascalCasing。 【参考方案1】:这个解决方案合适吗
基本上,是的。这是一种生产者/消费者的情况,而这正是 BlockingCollection 的用途。
这有什么问题吗?
您必须非常确定 doSomeBackgroundWork()
对于您的 doWork() 代码是线程安全的。
根据可以推送的 myEventArgs 数量,为您的阻塞集合设置一个上限可能是个好主意。
【讨论】:
太好了,非常感谢。 doSomeBackgroundWork() 方法本质上是一个查询第三方作业管理器的 SQL 选择语句。它不会更新或改变任何东西,所以它应该是安全的。【参考方案2】:我知道这是一个旧线程,但为了读者,我想指出,这样做与只产生没有阻塞集合的线程相同,因此删除了 BlockingCollection 的全部意义.
在这种情况下更合适的是管理线程数量,并且只产生特定数量的线程,同时消耗 BlockingCollection,这样可以确保不会同时产生太多线程
【讨论】:
是的,就像这个例子使用了四个线程:***.com/questions/22688679/…以上是关于c#阻塞收集和线程的主要内容,如果未能解决你的问题,请参考以下文章