异步运行多个任务并等待其结果c#

时间:2016-06-24 08:10:25

标签: c# .net asynchronous async-await

在我的服务层中,我想异步触发多个方法并等待其结果。

我一次尝试一个,这是错误的。

在我的服务类中,我调用了类似

的方法
var _validChapterCodesTask = gd.validateChapterCodeDetails(_input1);

await Task.WhenAll(_validChapterCodesTask);

var _chapterCodeResult = await  _validChapterCodesTask;

DAL类中,方法定义类似于

 public async Task<IEnumerable<ChapterCodeValidationOutput>> validateChapterCodeDetails(GroupMembershipValidationInput gmvi)
 {
     Repository rep = new Repository();
     if (!gmvi._chapterCodes.All(x => x.Equals("")))
     {
         var _validChapterCodes = await rep.ExecuteStoredProcedureAsync<Entities.Upload.ChapterCodeValidationOutput>(SQL.Upload.UploadValidation.getChapterCodeValidationSQL(gmvi._chapterCodes),null);
         return _validChapterCodes;
     }
     else
         return new List<ChapterCodeValidationOutput>();
 }

错误消息

  

错误208 await运算符只能在async方法中使用。请考虑使用async修饰符标记此方法,并将其返回类型更改为Task<ARC.Donor.Business.Upload.GroupMembershipValidationOutput>C:\Users\m1034699\Desktop\Stuart_Upgrade_2.1_New Approach\Stuart_Export_Upload_v2.1\Stuart Web Service\ARC.Donor.Service\Upload\UploadValidationServices.cs 34 13 ARC.Donor.Service

await Task.WhenAll(_validChapterCodesTask);

var _chapterCodeResult = await  _validChapterCodesTask; 

我做错了什么?

2 个答案:

答案 0 :(得分:1)

错误消息非常明确。它告诉您,您服务类方法错误地尝试使用async关键字。为了解决这个问题,您应该使用Stephen Cleary在MSDN上发布的"Async all the way"作为最佳做法。

例如,如果您的服务类具有使用TaskTask<T>的方法正文,或尝试使用await关键字,则此方法签名对应此方法正文必须为async(因为async关键字允许方法使用await关键字)。此外,此方法本身也应该TaskTask<T>返回,该规则的例外情况非常少。

就个人而言,我会改变你的 DAL 类,只是返回代表异步工作的操作而不实际等待它。如果你考虑一下,validateChapterCodeDetails方法的主体实际上需要对结果做任何事情,它只需要返回它们(而不是在那里实现它们)。请考虑以下事项:

public Task<IEnumerable<ChapterCodeValidationOutput>> 
    validateChapterCodeDetails(GroupMembershipValidationInput gmvi)
{
     var rep = new Repository();
     return gmvi._chapterCodes.All(x => x.Equals(""))
         ? new List<ChapterCodeValidationOutput>()
         : rep.ExecuteStoredProcedureAsync
               <Entities.Upload.ChapterCodeValidationOutput>
                   (SQL.Upload.UploadValidation
                              .getChapterCodeValidationSQL(gmvi._chapterCodes),null)
}

由于您已经等待Task<IEnumerable<ChapterCodeValidationOutput>>变量,因此您可以访问.Result属性以获取您要查找的内容。 然后在服务类中,您的方法将如下所示:

public async Task ConsumeAsync()
{
    var _validChapterCodesTask = gd.validateChapterCodeDetails(_input1);

    await Task.WhenAll(_validChapterCodesTask);

    var _chapterCodeResult = _validChapterCodesTask.Result;
    // Do something with it...
}

Here is a .NET fiddle应该有助于更好地为您举例说明。

注意

我还要谨慎使用IEnumerable因为它与你的回购有关,你应该确保数据库的结果不会通过延期执行发生,否则你冒着连接问题的风险,即;无意中断开连接,或者没有正确关闭连接。

答案 1 :(得分:0)

在您致电的Service班级

var _validChapterCodesTask = gd.validateChapterCodeDetails(_input1);

await Task.WhenAll(_validChapterCodesTask);

var _chapterCodeResult = await  _validChapterCodesTask;

在方法签名中添加async,其中await Task.WhenAll(_validChapterCodesTask);被调用。当此方法也有返回类型时,您必须将此类型包装在Task中,如异常所示:

Task<ARC.Donor.Business.Upload.GroupMembershipValidationOutput>

E.g。如果你有以下方法:

public GroupMemberShipValidationOutput validate(..) {
   ...
   await Task.WhenAll(_validChapterCodesTask);
   ...
}

您必须将方法签名更改为:

public async Task<GroupMemberShipValidationOutput> validate(..) {
   ...
   await Task.WhenAll(_validChapterCodesTask);
   ...
}