c#中的并行与任务

本文关键字:任务 并行 | 更新日期: 2023-09-27 18:04:35

我有一个方法,它需要进行多个服务调用并合并结果。我试着用Task来做这个,结果不正确,所以我做了下面两个测试。

使用任务

List<Task<string>> tasks = new List<Task<string>>();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 20; i++)
{
    tasks.Add(Task.Factory.StartNew(() =>
        {
            long started = stopwatch.ElapsedMilliseconds;
            Random wait = new Random();
            int waited = wait.Next(500, 3000);
            Thread.Sleep(waited);
            return string.Format("Index #{0} started at {1}ms and waited {2}ms", i, started, waited);
        }));
}
Task.WaitAll(tasks.ToArray());
foreach (Task<string> task in tasks)
{
    Console.WriteLine(string.Format("[Task {0,2}] {1}", task.Id, task.Result));
}
使用并行

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
int[] inputs = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
Parallel.ForEach(inputs, i =>
{
    long started = stopwatch.ElapsedMilliseconds;
    Random wait = new Random();
    int waited = wait.Next(500, 3000);
    Thread.Sleep(waited);
    string result = string.Format("Task {0,2} started at {1} ms and waited {2} ms", i, started, waited);
    Console.WriteLine(result);
});
stopwatch.Stop();
Console.WriteLine("Total time taken: " + stopwatch.ElapsedMilliseconds.ToString());

如下所示,任务索引一直被打印为20(尽管传递的是0到19)。而且,并行比任务花费更多的时间。下面是结果,显然我在任务中做错了什么,无法弄清楚是什么:(

任务输出

[Task  1] Index #20 started at 0ms and waited 875ms
[Task  2] Index #20 started at 0ms and waited 875ms
[Task  3] Index #20 started at 0ms and waited 875ms
[Task  4] Index #20 started at 0ms and waited 875ms
[Task  5] Index #20 started at 0ms and waited 875ms
[Task  6] Index #20 started at 0ms and waited 875ms
[Task  7] Index #20 started at 855ms and waited 1477ms
[Task  8] Index #20 started at 886ms and waited 1965ms
[Task  9] Index #20 started at 886ms and waited 1965ms
并行输出

Task  6 started at 1046 ms and waited 636 ms
Task 11 started at 1561 ms and waited 758 ms
Task  0 started at 16 ms and waited 2891 ms
Task  5 started at 16 ms and waited 2891 ms
Task 15 started at 17 ms and waited 2891 ms
Task  1 started at 17 ms and waited 2891 ms
Task 10 started at 17 ms and waited 2891 ms

对于实际方法,我也有相同的经验,其中最后一项被多次返回,而不是单个结果。

如果你能给我指路就太好了。

注:输出是局部的。实际输出为20项

c#中的并行与任务

您需要对i形成一个闭包。下面是最简单的方法:

for (int x = 0; x < 20; x++)
{
    var i = x;
    tasks.Add(...) // keep using `i` inside here & never `x`
}

当使用任务方法时,您在'i'上有一个闭包,这就是为什么所有任务id都显示为20(即。当任务实际执行时,所有20个任务都已被调度,因此当方法执行时I == 20)。

Parallel主要用于允许您扩展算法以使用机器上可用的CPU资源。如果问题不是CPU限制(即调用WebServices)并行不是正确的抽象。

所以在你的情况下,任务似乎是正确的选择。