我有一个Windows服务来处理用户创建的任务。此服务在具有4个核心的服务器上运行。这些任务主要涉及繁重的数据库工作(例如生成报告)。服务器还运行了一些其他服务,所以我不想激活太多的线程(假设最多4个)。
如果我使用BlockingCollection<MyCustomTask>
,最好创建4个Thread对象并使用这些对象来使用BlockingCollection<MyCustomTask>
,还是应该使用Parallel.Foreach
来完成此操作?
我正在查看包含StaTaskScheduler的ParallelExtensionsExtras,它使用前者,就像这样(为了清晰起见,稍微修改了代码):
var threads = Enumerable.Range(0, numberOfThreads).Select(i =>
{
var thread = new Thread(() =>
{
// Continually get the next task and try to execute it.
// This will continue until the scheduler is disposed and no more tasks remain.
foreach (var t in _tasks.GetConsumingEnumerable())
{
TryExecuteTask(t);
}
});
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
return thread;
}).ToList();
// Start all of the threads
threads.ForEach(t => t.Start());
但是,同一个ParallelExtensionsExtras中还有一个BlockingCollectionPartitioner
可以在Parallel.Foreach
上使用BlockingCollection<Task>
,如下所示:
var blockingCollection = new BlockingCollection<MyCustomTask>();
Parallel.ForEach(blockingCollection.GetConsumingEnumerable(), task =>
{
task.DoSomething();
});
我理解后者利用ThreadPool
。在这种情况下使用Parallel.ForEach会有什么好处吗?
答案 0 :(得分:3)
如果您的代码中的Task类与System.Threading.Tasks.Task无关,那么这个答案是相关的。
作为一个简单的规则,使用Parallel.ForEach来运行最终结束的任务。就像执行一些与其他工作并行的工作
在应用程序的整个生命周期中运行例程时使用线程。
因此,在您的情况下,您应该使用Threads方法。