Parallel.ForEach和异步的await [英] Parallel.ForEach and async-await

查看:1212
本文介绍了Parallel.ForEach和异步的await的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的方法:

 公共异步任务< MyResult>调用getResult()
{
    MyResult结果=新MyResult();    的foreach(在方法VAR法)
    {
        JSON字符串等待=程序(方法);        result.Prop1 = PopulateProp1(JSON);
        result.Prop2 = PopulateProp2(JSON);    }    返回结果;
}

然后我决定用 Parallel.ForEach

 公共异步任务< MyResult>调用getResult()
{
    MyResult结果=新MyResult();    Parallel.ForEach(方法,异步方法= GT;
    {
        JSON字符串等待=程序(方法);        result.Prop1 = PopulateProp1(JSON);
        result.Prop2 = PopulateProp2(JSON);
    });    返回结果;
}

但现在我已经得到了一个错误:


  

而异步操作仍然悬而未决的异步模块或处理程序完成。



解决方案

异步的ForEach 。特别是,你的异步拉姆达被转换为异步无效方法。有一些原因,以避免异步无效 (我描述了MSDN文章中);其中之一是,当异步拉姆达已完成你不能轻易察觉。 ASP.NET会看到没有完成的异步无效方法(适当地)抛出一个异常,你的code的回报。

您可能想要做的是处理数据的同时的,只是没有在的平行的。并行code应该几乎从不在ASP.NET中使用。这里的code会是什么样子异步并行处理:

 公共异步任务< MyResult>调用getResult()
{
  MyResult结果=新MyResult();  VAR任务= Methods.Select(方法=> ProcessAsync(法))ToArray的()。
  字符串[] = JSON等待Task.WhenAll(任务);  result.Prop1 = PopulateProp1(JSON [0]);
  ...  返回结果;
}

I had such method:

public async Task<MyResult> GetResult()
{
    MyResult result = new MyResult();

    foreach(var method in Methods)
    {
        string json = await Process(method);

        result.Prop1 = PopulateProp1(json);
        result.Prop2 = PopulateProp2(json);

    }

    return result;
}

Then I decided to use Parallel.ForEach:

public async Task<MyResult> GetResult()
{
    MyResult result = new MyResult();

    Parallel.ForEach(Methods, async method =>
    {
        string json = await Process(method);    

        result.Prop1 = PopulateProp1(json);
        result.Prop2 = PopulateProp2(json);
    });

    return result;
}

But now I've got an error:

An asynchronous module or handler completed while an asynchronous operation was still pending.

解决方案

async doesn't work well with ForEach. In particular, your async lambda is being converted to an async void method. There are a number of reasons to avoid async void (as I describe in an MSDN article); one of them is that you can't easily detect when the async lambda has completed. ASP.NET will see your code return without completing the async void method and (appropriately) throw an exception.

What you probably want to do is process the data concurrently, just not in parallel. Parallel code should almost never be used on ASP.NET. Here's what the code would look like with asynchronous concurrent processing:

public async Task<MyResult> GetResult()
{
  MyResult result = new MyResult();

  var tasks = Methods.Select(method => ProcessAsync(method)).ToArray();
  string[] json = await Task.WhenAll(tasks);

  result.Prop1 = PopulateProp1(json[0]);
  ...

  return result;
}

这篇关于Parallel.ForEach和异步的await的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆