使用 Parallel.ForEach 启动两个并行任务
Start two parallel tasks with Parallel.ForEach
在此代码中 Parallel.ForEach
没有等待。经过的秒数立即 returning 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
作为 return 类型和此代码进行了尝试:
Parallel.Invoke(async() => await ExecuteTaskAAsync(), async() => await ExecuteTaskBAsync());
同样,经过的秒数立即 return 变为 0。我怎样才能 运行 两个任务并行?
并行工作正常 - 它正在开始 两个并行任务,正如您的代码所要求的那样。它只是不等待这些任务完成(即使是,这些任务也不会等待您的 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 void
是不自然的,应该只用于事件处理程序。有关详细信息,请参阅我在 async best practices 上的 MSDN 文章。
最后一点,you should never use the Task
constructor。我在我的博客上进行了详细解释,但归结为:总是 更好的选择。
在此代码中 Parallel.ForEach
没有等待。经过的秒数立即 returning 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
作为 return 类型和此代码进行了尝试:
Parallel.Invoke(async() => await ExecuteTaskAAsync(), async() => await ExecuteTaskBAsync());
同样,经过的秒数立即 return 变为 0。我怎样才能 运行 两个任务并行?
并行工作正常 - 它正在开始 两个并行任务,正如您的代码所要求的那样。它只是不等待这些任务完成(即使是,这些任务也不会等待您的 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 void
是不自然的,应该只用于事件处理程序。有关详细信息,请参阅我在 async best practices 上的 MSDN 文章。
最后一点,you should never use the Task
constructor。我在我的博客上进行了详细解释,但归结为:总是 更好的选择。