C# 中的线程同步

本文关键字:同步 线程 | 更新日期: 2023-09-27 18:30:48

在我的应用程序中,我使用不同的线程(每个活动传输一个线程)。例如,我想限制活动的转换器,将其他即将到来的转换器放在队列中。

目前,我的解决方案是检查是否有空间进行另一个活动传输,如果没有,我会将请求放在队列列表中。每次我完成活动时,我都会从队列中选择一个。(但我想我的解决方案真的很脏)

有没有一种很好的方法来调度活动线程?

使用信号灯是一个不错(且整洁)的选择吗?

C# 中的线程同步

您可以使用 BlockingCollection 来管理队列,例如:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace Demo
{
    public class Program
    {
        private readonly BlockingCollection<int> _queue = new BlockingCollection<int>();
        private void run()
        {
            const int CONSUMER_COUNT = 8;
            Task[] tasks = new Task[CONSUMER_COUNT];
            for (int i = 0; i < CONSUMER_COUNT; ++i)
            {
                int id = i;
                tasks[i] = Task.Run(() => process(id));
            }
            Console.WriteLine("Press <return> to start adding to the queue.");
            Console.ReadLine();
            for (int i = 0; i < 100; ++i)
            {
                Console.WriteLine("Adding item #{0}", i);
                _queue.Add(i);
            }
            Console.WriteLine("Press <return> to close the queue.");
            Console.ReadLine();
            _queue.CompleteAdding();
            Console.WriteLine("Waiting for all tasks to exit.");
            Task.WaitAll(tasks);
            Console.WriteLine("Finished waiting for all tasks. Press <return> to exit.");
            Console.ReadLine();
        }
        private void process(int id)
        {
            Console.WriteLine("Process {0} is starting.", id);
            foreach (var item in _queue.GetConsumingEnumerable())
            {
                Console.WriteLine("Process {0} is processing item# {1}", id, item);
                Thread.Sleep(200); // Simulate long processing time.
            }
            Console.WriteLine("Process {0} is stopping.", id);
        }
        private static void Main()
        {
            new Program().run();
        }
    }
}

请注意,这里的关键是GetConsumingEnumerable()返回一个枚举对象,如果队列中没有项目,它将阻塞,但如果没有项目并且生产者调用了CompleteAdding(),它将退出。这使得控制工作线程何时退出变得非常容易。