简体   繁体   English

C#中的线程同步

[英]Thread synchronization in C#

in my application I use different threads (one for every active transfer). 在我的应用程序中,我使用不同的线程(每个活动传输一个)。 I would for example want to limit the active tranfers, putting the other coming ones in a queue. 例如,我想限制活动的转移,将其他即将到来的转移入队列。

For now my solution was checking if there was space for another active transfer, if not I would put the request in a queue list. 现在,我的解决方案是检查是否有空间进行另一个活动传输,否则,我会将请求放入队列列表中。 Everytime I've a completed event, I pick one from the queue. 每当我完成一个活动时,我都会从队列中选择一个。 (but I guess that my solution is really dirty) (但我想我的解决方案真的很脏)

Is there a nice way to schedule the active threads? 有没有计划活动线程的好方法?

Is using a semaphore a nice (and neat) choice? 使用信号灯是不错的选择吗?

You could use a BlockingCollection to manage the queue, for example: 您可以使用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();
        }
    }
}

Note that the crucial thing here is that GetConsumingEnumerable() returns an enumerable which will block if there are no items in the queue, but which will exit if there no items and the producer has called CompleteAdding() . 请注意,这里的关键是GetConsumingEnumerable()返回一个枚举,如果队列中没有任何项目,它将阻塞,但是如果没有项目并且生产者调用了CompleteAdding() ,它将退出。 This makes it quite easy to control when the worker threads exit. 这使得控制工作线程何时退出非常容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM