c#阻塞收集和线程

本文关键字:线程 | 更新日期: 2023-09-27 18:15:34

我是使用阻塞集合和线程的新手,并希望确保我遵循最佳实践。我使用的是不线程安全的第三方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方法?

c#阻塞收集和线程

这个方案合适吗

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

这个有什么问题吗?

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

在你的blockingcollection上设置一个上限可能是一个好主意,这取决于可以推送多少myEventArgs。

我知道这是一个老线程,但为了读者的缘故,我想指出,这样做,是一样的,只是产卵线程没有阻塞集合,从而消除了BlockingCollection的整个点。

在这种情况下,更合适的方法是管理线程的数量,并且在使用BlockingCollection时只产生特定数量的线程,这样可以确保同时不会产生太多的线程