c#阻止收集和线程

时间:2016-10-31 09:22:20

标签: c# multithreading thread-safety threadpool blockingcollection

我很擅长使用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方法?

2 个答案:

答案 0 :(得分:2)

  

此解决方案是否合适

基本上,是的。这是生产者/消费者的情况,这正是BlockingCollection的用途。

  

有什么可能出错吗?

您必须非常确定doSomeBackgroundWork()对于您的doWork()代码是线程安全的。

最好在您的blockingcollection上设置一个上限,这取决于可以推送多少个myEventArgs。

答案 1 :(得分:0)

我知道这是一个旧线程,但是为了读者,我想指出的是,以这种方式进行操作与仅生成没有阻塞集合的线程相同,因此消除了BlockingCollection的全部内容

在这种情况下,更合适的方法是管理线程数,并且仅在使用BlockingCollection时才产生特定数量的线程,这将确保不会同时产生太多线程< / p>