使用Parallel.ForEach启动两个并行任务

时间:2016-05-18 15:19:00

标签: c# multithreading parallel.foreach

在此代码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.如何并行运行这两个任务?

1 个答案:

答案 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。我在我的博客上详细解释,但它归结为: 总是是一个更好的选择。