启动任务和获取返回值的更好模式

时间:2014-11-11 13:00:32

标签: c# .net task-parallel-library

我正在实施一些异步工作并且无法提供帮助,但我觉得我最终会得到一个非常难看的结构,我想知道是否以及如何将其重写为“#”;感觉更好'。

 var tasks = new List<Task>();

 var t1 = new Task<Guid>(() => DoSomeStuff<Xyz>(dtx, e1, M1));
 var t2 = new Task<Guid>(() => DoSomeStuff<Qrs>(dtx, e2, M2));
 var t3 = new Task<Guid>(() => DoSomeStuff<Abc>(dtx, e3, M3));

 tasks.Add(t1);
 tasks.Add(t2);
 tasks.Add(t3);

 tasks.ForEach(x => x.Start());

 Task.WaitAll(tasks.ToArray<Task>());

 returnDto.t1value = t1.Result;
 returnDto.t2value = t2.Result;
 returnDto.t3value = t3.Result;

为简洁起见,变量名称已被更改,实际上还有更多任务。 任务都可以独立运行,但所有任务都必须在我们继续之前完成。

DoSomeStuff看起来像这样:

private Guid DoSomeStuff<T>(DependentTransaction dtx, T thing, Func<T, Guid> method)

2 个答案:

答案 0 :(得分:5)

使用async-await异步等待,Task.WhenAll等待多个任务并获得结果并Task.Run并行运行DoSomeStuff会更容易:< / p>

Guid[] results = await Task.WhenAll(
    Task.Run(() => DoSomeStuff<Xyz>(dtx, e1, M1)),
    Task.Run(() => DoSomeStuff<Qrs>(dtx, e2, M2)), 
    Task.Run(() => DoSomeStuff<Abc>(dtx, e3, M3)));

答案 1 :(得分:1)

  

我正在实施一些异步工作

区分异步并行工作非常重要。异步工作通常是基于I / O的,而并行工作则使用多个线程来处理CPU绑定的代码。

如果您的工作是异步的,那么您应该使用异步API将DoSomeStuff转换为async方法。完成后,进行并发异步工作相对容易:

Guid[] results = await Task.WhenAll(DoSomeStuffAsync<Xyz>(dtx, e1, M1),
    DoSomeStuffAsync<Qrs>(dtx, e2, M2), DoSomeStuffAsync<Abc>(dtx, e3, M3));

但是,如果您的工作是并行的,那么最好使用Parallel类(或并行LINQ):

Guid[] results = new Guid[3];
Parallel.Invoke(() => { results[0] = DoSomeStuff<Xyz>(dtx, e1, M1); },
    () => { results[1] = DoSomeStuff<Qrs>(dtx, e2, M2); },
    () => { results[2] = DoSomeStuff<Abc>(dtx, e3, M3); });