【发布时间】:2014-02-26 08:40:19
【问题描述】:
我有大约 500 个任务,每个任务需要大约 5 秒,大部分时间都浪费在等待远程资源回复上。我想定义自己应该产生的线程数(经过一些测试)并在这些线程上运行任务。当一个任务完成时,我想在可用的线程上生成另一个任务。
我发现System.Threading.Tasks最容易实现我想要的,但我认为不可能指定应该并行执行的任务数量。对于我的机器,它总是在 8 左右(四核 cpu)。是否有可能以某种方式告诉应该并行执行多少个任务?如果不是,实现我想要的最简单的方法是什么? (我尝试使用线程,但代码要复杂得多)。我尝试增加MaxDegreeOfParallelism参数,但它只限制了最大数量,所以这里没有运气......
这是我目前拥有的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
private static List<string> _list = new List<string>();
private static int _toProcess = 0;
static void Main(string[] args)
{
for (int i = 0; i < 1000; ++i)
{
_list.Add("parameter" + i);
}
var w = new Worker();
var w2 = new StringAnalyzer();
Parallel.ForEach(_list, new ParallelOptions() { MaxDegreeOfParallelism = 32 }, item =>
{
++_toProcess;
string data = w.DoWork(item);
w2.AnalyzeProcessedString(data);
});
Console.WriteLine("Finished");
Console.ReadKey();
}
static void Done(Task<string> t)
{
Console.WriteLine(t.Result);
--_toProcess;
}
}
class Worker
{
public string DoWork(string par)
{
// It's a long running but not CPU heavy task (downloading stuff from the internet)
System.Threading.Thread.Sleep(5000);
return par + " processed";
}
}
class StringAnalyzer
{
public void AnalyzeProcessedString(string data)
{
// Rather short, not CPU heavy
System.Threading.Thread.Sleep(1000);
Console.WriteLine(data + " and analyzed");
}
}
}
【问题讨论】:
-
使用比处理器内核更多的任务通常会减慢它的速度。这就是它受到限制的原因。我猜它限制在 8 个,因为你有 8 个逻辑核心的四核 + 超线程。
-
恕我直言,您遇到了设计问题。通过创建更多线程来解决这个问题是个坏主意。您应该使用 I/O 完成端口。
-
@MatthewWatson “大部分时间都浪费在等待远程资源回复上”,所以我认为使用比内核数更多的线程不会有问题在这里(只要远程服务器对此感到满意:))
-
@MichalB。创建花费大部分时间等待的任务是一个很大的禁忌。你不应该那样做。需要不同的设计——正如 Fyodor 所说,IO Completion Ports 是一个可能的解决方案。但是创建一个完整的线程负载确实是一个非常糟糕的主意。
-
@MichalB。告诉你不要做错事很有用,不是吗?它至少会引导你远离糟糕的解决方案。
标签: c# .net parallel-processing parallel.foreach