在此代码Parallel.ForEach
中没有等待。经过的秒数会立即返回0.此代码位于PCL中:
private void Button_Clicked(object sender, EventArgs e)
{
Stopwatch watch = new Stopwatch();
watch.Start();
List<Task> taskList = new List<Task>();
Task taskA = new Task(ExecuteTaskAAsync);
Task taskB = new Task(ExecuteTaskBAsync);
taskList.Add(taskA);
taskList.Add(taskB);
Parallel.ForEach(taskList, t => t.Start());
watch.Stop();
System.Diagnostics.Debug.WriteLine("Seconds Elapsed: " + watch.Elapsed.Seconds);
}
private async void ExecuteTaskAAsync()
{
for (int i = 0; i < 10; i++)
{
System.Diagnostics.Debug.WriteLine("Task A: [{0}]", i + 1);
await Task.Delay(1000);
}
System.Diagnostics.Debug.WriteLine("Finished Task A!");
}
private async void ExecuteTaskBAsync()
{
for (int i = 0; i < 10; i++)
{
System.Diagnostics.Debug.WriteLine("Task B: [{0}]", i + 1);
await Task.Delay(1000);
}
System.Diagnostics.Debug.WriteLine("Finished Task B!");
}
对此行为负责似乎是t.Start()
,它启动了一个新主题并且Parallel.ForEach
已完成。我也尝试使用Task
作为返回类型和此代码:
Parallel.Invoke(async() => await ExecuteTaskAAsync(), async() => await ExecuteTaskBAsync());
经过秒数后立即返回0.如何并行运行这两个任务?
答案 0 :(得分:3)
并行工作正常 - 它正在开始两个任务并行,就像你的代码要求它一样。它只是不等待完成这些任务(即使是这样,这些任务也不等待你的handleClientLoad
方法完成)。
由于您正在处理异步任务,您真正想要的是异步并发,而不是并行并发。它们是两种并发(同时做多个事情),但并行性是关于产生多个线程,而异步是关于释放当前线程。
异步并发使用async void
,因此:
Task.WhenAll
另请注意,我将现有的private async void Button_Clicked(object sender, EventArgs e)
{
Stopwatch watch = new Stopwatch();
watch.Start();
Task taskA = ExecuteTaskAAsync();
Task taskB = ExecuteTaskBAsync();
await Task.WhenAll(taskA, taskB);
watch.Stop();
System.Diagnostics.Debug.WriteLine("Seconds Elapsed: " + watch.Elapsed.Seconds);
}
private async Task ExecuteTaskAAsync()
{
for (int i = 0; i < 10; i++)
{
System.Diagnostics.Debug.WriteLine("Task A: [{0}]", i + 1);
await Task.Delay(1000);
}
System.Diagnostics.Debug.WriteLine("Finished Task A!");
}
private async Task ExecuteTaskBAsync()
{
for (int i = 0; i < 10; i++)
{
System.Diagnostics.Debug.WriteLine("Task B: [{0}]", i + 1);
await Task.Delay(1000);
}
System.Diagnostics.Debug.WriteLine("Finished Task B!");
}
方法更改为async void
;这是因为async Task
不自然,应该只用于事件处理程序。有关详细信息,请参阅async best practices上的MSDN文章。
最后一点,you should never use the Task
constructor。我在我的博客上详细解释,但它归结为: 总是是一个更好的选择。