简体   繁体   English

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

[英]Start two parallel tasks with Parallel.ForEach

In this code Parallel.ForEach is not waiting. 在这段代码中, Parallel.ForEach没有等待。 Seconds elapsed is immediately returning 0. This code is in a PCL: 经过的秒数会立即返回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!");
}

Responsible for this behavior seems to be t.Start() , which starts a new thread and Parallel.ForEach has finished. 负责此行为似乎是t.Start() ,它启动一个新线程并且Parallel.ForEach已经完成。 I also tried it by using Task as return type and this code: 我也尝试使用Task作为返回类型和此代码:

Parallel.Invoke(async() => await ExecuteTaskAAsync(), async() => await ExecuteTaskBAsync());

Again seconds elapsed is immediately returning 0. How can I run both tasks parallel? 经过的秒数会立即返回0.如何同时运行两个任务?

The parallel is working just fine - it's starting both tasks in parallel, just as your code is asking it to. 并行工作正常 - 它正在并行启动两个任务,就像您的代码要求它一样。 It's just not waiting for those tasks to complete (and even if it was, those tasks aren't waiting for your async void methods to complete). 它只是不等待完成这些任务(即使它是,那些任务不等待您的async void方法完成)。

Since you're dealing with asynchronous tasks, what you really want is asynchronous concurrency , not parallel concurrency . 由于您正在处理异步任务,您真正想要的是异步并发 ,而不是并行并发 They're both kinds of concurrency (doing more than one thing at the same time), but parallelism is about spawning multiple threads, whereas asynchrony is about freeing up the current thread. 它们是两种并发同时做多个事情),但并行性是关于产生多个线程,而异步则是关于释放当前线程。

Asynchronous concurrency works by using Task.WhenAll , as such: 异步并发使用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!");
}

Also note that I changed the existing async void methods to async Task ; 另请注意,我将现有的async void方法更改为async Task ; this is because async void is unnatural and should be only used for event handlers. 这是因为async void不自然,应该只用于事件处理程序。 See my MSDN article on async best practices for more info. 有关详细信息,请参阅我的MSDN有关异步最佳实践的文章。

As a final note, you should never use the Task constructor . 最后要注意, 您永远不应该使用Task构造函数 I explain in detail on my blog, but it comes down to: there's always a better alternative. 我在我的博客上详细解释,但它归结为: 有一个更好的选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM