我的代码中有几种情况,各种线程可以创建工作项,由于各种原因,不应该并行完成。我想确保工作以FIFO方式完成,无论它来自哪个线程。在Java中,我将工作项放在单线程ExecutorService
上;在C#中是否有等价物?我用Queue
和一堆lock(){}
块拼凑了一些东西,但是能够使用现成的和经过测试的东西会很棒。
更新:是否有人有使用System.Threading.Tasks的经验?它有这种解决方案吗?我正在写一个Monotouch应用程序,所以谁知道我是否能找到一个我可以开始工作的移植版本,但它至少应该考虑未来。
更新#2 对于不熟悉我正在谈论的Java库的C#开发人员,基本上我想要一些能让各个线程切换工作项的东西,以便所有这些工作项都能运行在单线程(不是任何调用线程)。
更新,6/201 :如果我现在正在构建一个类似的系统,我可能会根据Reactive Extensions使用Matt Craig's answer。但是,我要离开Zachary Yates' answer被接受的那个,因为如果你在Rx中思考,你可能甚至不会问这个问题,我认为ConcurrentQueue
更容易躲到前Rx程序
答案 0 :(得分:4)
您可以使用ConcurrentQueue,(如果monotouch支持.net 4?)它是线程安全的,我认为实现实际上是无锁的。如果您有一个长时间运行的任务(如在Windows服务中),这非常有效。
通常情况下,您的问题听起来像是有多个生产者只有一个消费者。
var work = new ConcurrentQueue<Item>();
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。 Here's an MSDN page显示所有新的并发集合类型。
答案 1 :(得分:1)
我相信这可以使用SynchronizationContext来完成。但是,我只是这样做回发到UI线程,它已经有.NET提供的同步上下文(如果被告知要安装) - 我不知道如何准备它从“vanilla线程”使用“虽然。
我找到的“自定义同步文本提供程序”的一些链接(我没有时间查看这些,不完全理解工作/上下文,也没有任何其他信息):
答案 2 :(得分:1)
现在有一种更现代的解决方案 - EventLoopScheduler类。
答案 3 :(得分:0)
不是原生AFAIK,但看看这个: Serial Task Executor; is this thread safe?
答案 4 :(得分:-2)
正如我在评论中所写,您自己发现lock
语句可以完成这项工作。
如果您有兴趣获得一个可以简化管理工作项队列的“容器”,请查看ThreadPool
类。
我认为,在设计良好的架构中,使用这两个元素(ThreadPool
类和lock
语句),您可以轻松且成功地序列化对资源的访问。