我有一个C#控制台应用程序,我用它来进行实验。我有一些代码块,我知道我想运行1)异步2)并行3)每个块完成时运行一些共享清理代码。
我需要异步运行块,因为每个块都在调用Web服务。出于性能原因,我需要并行运行每个块,并且没有块依赖于另一个块。最后,我有大量的清理和日志记录代码,我想在每个块完成时运行。因此,此代码是共享的。
我被困在如何做到这一点。到目前为止,我已经看了下面的C#概念:
1)Tasks - 优点:擅长异步运行代码缺点:a)我没有看到定义任务并将其传递给共享方法的方法,以便我可以运行清理代码。 b)我没有看到将参数传递给任务的好方法
2)Actions - 优点:a)可以定义内联的代码块,即var myAction = (Action)(() => { });
。 b)可以轻松地将参数传递给Action
。缺点:似乎不是异步运行动作的一种方式,因此b)不确定我可以并行运行动作。
在我写这个问题时,我很清楚我错过了什么。乍一看,任务似乎是正确的道路。但是,我确实感到困惑于
public void RunTaskInParallel(Task task)
{
var startTime = DateTime.UtcNow;
// Execute task code
var executionTime = DateTime.UtcNow.Subtract(startTime);
// Log the execution time
// Execute Clean-up Code
}
如何以并行方式异步运行代码块,以便在完成所有操作后允许我执行一些共享清理代码?我觉得我总是得到三分之二的要求,但努力争取全部三个。
感谢您的帮助!
答案 0 :(得分:0)
您可以创建一个需要并行执行的任务列表,然后异步等待所有任务都以Task.WhenAll
静态方法完成:
await Task.WhenAll(new []{ RoutineA(), RoutineB()});
Cleanup();
RoutineA
和RoutineB
可以是async
个函数,返回Task
。请注意,我们不会await
这些调用 - 因此调用线程在启动RoutineB
后会继续触发RoutineA
。
答案 1 :(得分:0)
您可以 .WhenAll 以并行和异步方式运行某项任务。
例如
Task a = AsyncTaskA();
Task b = AsyncTaskB();
Task c = AsyncTaskC();
List<Task> AllTasks = new List<Task>();
AllTasks.Add(a);
AllTasks.Add(b);
AllTasks.Add(c);
// this will run all your tasks async and parallel and also wait until everything is done
await Task.WhenAll(AllTasks);
答案 2 :(得分:-1)
我会使用Task.WaitAll
,它看起来像:
var stopwatch = new Stopwatch();
stopwatch.Start();
Action<string> logTime = (label) => Console.WriteLine($"{label}: {stopwatch.Elapsed.Seconds} in Seconds");
var taskList = new List<Task>();
taskList.Add(Task.Run(() => { DoWork(); logTime("Task 1");}));
taskList.Add(Task.Run(() => { DoWork(); logTime("Task 2"); }));
taskList.Add(Task.Run(() => { DoWork(); logTime("Task 3"); }));
taskList.Add(Task.Run(() => { DoWork(); logTime("Task 4"); }));
taskList.Add(Task.Run(() => { DoWork(); logTime("Task 5"); }));
taskList.Add(Task.Run(() => { DoWork(); logTime("Task 6"); }));
taskList.Add(Task.Run(() => { DoWork(); logTime("Task 7"); }));
taskList.Add(Task.Run(() => { DoWork(); logTime("Task 8"); }));
await Task.Run(()=>Task.WaitAll(taskList.ToArray()));
stopwatch.Stop();
var timeRan = stopwatch.Elapsed.Seconds;
//log time
logTime("Total Time");
Console.ReadLine();