Java ExecutorService.newSingleThreadExecutor()的C#等价物,或者:如何序列化对资源的multithreading访问

我的代码中有几种情况,各种线程可以创建工作项,由于各种原因,不应该并行完成。 我想确保工作以FIFO方式完成,无论它来自哪个线程。 在Java中,我将工作项放在单线程ExecutorService ; 在C#中是否有等价物? 我用Queue和一堆lock(){}块拼凑了一些东西,但是能够使用现成的和经过测试的东西会很好。

更新:有没有人有System.Threading.Tasks的经验? 它有这种解决方案吗? 我正在写一个Monotouch应用程序,所以谁知道我是否能找到它可以开始工作的它的后向版本,但它至少是为未来考虑的事情。

更新#2对于不熟悉我正在谈论的Java库的C#开发人员,基本上我想要一些东西让各个线程交出工作项,这样所有这些工作项都将在一个线程上运行(这不是任何一个调用线程)。


更新,6/201 :如果我现在正在构建一个类似的系统,我可能会根据Matt Craig的回答使用Reactive Extensions 。 我离开Zachary Yates回答了被接受的答案 ,因为如果你在Rx中思考,你可能甚至都不会问这个问题,我认为ConcurrentQueue更容易进入前Rx程序。

您可以使用ConcurrentQueue (如果monotouch支持.net 4?)它的线程安全,我认为实现实际上是无锁的。 如果您有一个长时间运行的任务(如在Windows服务中),这非常有效。

通常,您的问题听起来就像您有多个生产者只有一个消费者。

 var work = new ConcurrentQueue(); var producer1 = Task.Factory.StartNew(() => { work.Enqueue(item); // or whatever your threads are doing }); var producer2 = Task.Factory.StartNew(() => { work.Enqueue(item); // etc }); var consumer = Task.Factory.StartNew(() => { while(running) { Item item = null; work.TryDequeue(out item); } }); Task.WaitAll(producer1, producer2, consumer); 

如果您有一个有限的工作项池,则应该使用BlockingCollection 。 这是一个MSDN页面,显示了所有新的并发集合类型。

相信这可以使用SynchronizationContext来完成。 但是,我只是这样做回发到UI线程,它已经有.NET提供的同步上下文(如果被告知要安装) – 我不知道如何准备它从“vanilla线程”使用“不过。

我找到“自定义同步文本提供程序”的一些链接(我没有时间查看这些,不完全理解工作/上下文,也没有任何其他信息):

  1. 寻找自定义SynchronizationContext的示例(unit testing需要)

  2. http://codeidol.com/csharp/wcf/Concurrency-Management/Custom-Service-Synchronization-Context/

快乐的编码。

现在有一个更现代的解决方案 – EventLoopScheduler类。

不是原生的AFAIK,但看看这个: Serial Task Executor; 这个线程安全吗?

正如我在评论中写的那样,你自己发现lock语句可以完成工作。

如果您有兴趣获得一个“容器”,可以简化管理工作项队列的工作,请查看ThreadPool类。

我认为,在一个设计良好的架构中,通过这两个元素( ThreadPool类和lock语句),您可以轻松且成功地序列化对资源的访问。