任务

时间:2017-05-30 09:01:39

标签: c# multithreading queue task

我在c#中有一些工作经理会收到要执行的任务,然后执行它们。任务将从不同的线程到达,但它们必须按接收顺序同时执行一个。 我不想要一个while循环,它将一直运行,检查它们是否是队列中的新任务。是否有内置队列或实现队列的简单方法,该队列将等待任务并同步执行它们而不用繁忙等待?

2 个答案:

答案 0 :(得分:0)

根据评论,您应该查看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())
{}

答案 1 :(得分:0)

您可以使用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();
    }