簡體   English   中英

具有任務的線程安全隊列

[英]Thread-safe queue with tasks

我在c#中有一些工作經理會收到要執行的任務,然后執行它們。 任務將從不同的線程到達,但它們必須按接收順序同時執行一個。 我不想要一個while循環,它將一直運行,檢查它們是否是隊列中的新任務。 是否有內置隊列或簡單的方法來實現一個隊列,它將等待任務並同步執行它們而不需要忙碌等待?

根據評論,您應該查看ConcurrentQueue以及BlockingCollection並使用GetConsumingEnumerable()而不是不需要的WHILE循環

BlockingCollection<YourClass> _collection =
            new BlockingCollection<YourClass>(new ConcurrentQueue<YourClass>());

_collection.Add() can be called from multiple threads

在單獨的線程上,您可以使用

foreach (var message in _collection.GetConsumingEnumerable())
{}

您可以使用SemaphoreSlim( https://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim ( v=vs.110 ).aspx)和ConcurrentQueue

例:

    private delegate void TaskBody();

    private class TaskManager
    {
        private ConcurrentQueue<TaskBody>
            TaskBodyQueue = new ConcurrentQueue<TaskBody>();

        private readonly SemaphoreSlim 
            TaskBodySemaphoreSlim = new SemaphoreSlim(1, 1);

        public async void Enqueue(TaskBody body)
        {
            TaskBodyQueue.Enqueue(body);

            await TaskBodySemaphoreSlim.WaitAsync();

            Console.WriteLine($"Cycle ...");

            if (TaskBodyQueue.TryDequeue(out body) == false) {
                throw new InvalidProgramException($"TaskBodyQueue is empty!");
            }

            body();

            Console.WriteLine($"Cycle ... done ({TaskBodyQueue.Count} left)");

            TaskBodySemaphoreSlim.Release();
        }
    }

    public static void Main(string[] args)
    {
        var random = new Random();
        var tm = new TaskManager();

        Parallel.ForEach(Enumerable.Range(0, 30), async number => {
            await Task.Delay(100 * number);

            tm.Enqueue(delegate {
                Console.WriteLine($"Print {number}");
            });
        });

        Task
            .Delay(4000)
            .Wait();

        WaitFor(action: "exit");
    }

    public static void WaitFor(ConsoleKey consoleKey = ConsoleKey.Escape, string action = "continue")
    {
        Console.Write($"Press {consoleKey} to {action} ...");

        var consoleKeyInfo = default(ConsoleKeyInfo);

        do {
            consoleKeyInfo = Console.ReadKey(true);
        }
        while (Equals(consoleKeyInfo.Key, consoleKey) == false);

        Console.WriteLine();
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM