【问题标题】:How to create a method that calls a bunch of methods asynchronously如何创建一个异步调用一堆方法的方法
【发布时间】:2015-11-09 22:11:29
【问题描述】:

我有以下方法:

private async void CreateSchedule(IEnumerable<DateTime> dates)
{
   using (var db = new SolverDbContext())
   {
      foreach (var date in dates)
      {
         var job = await client.ConfigureJob(new JobConfigurationModel
         {
            ScheduleDate = date.ToString("yyyy-MM-dd"),
            // Bunch of other stuff that doesn't matter
         });

         var dbSchedule = Schedule.Default;
         dbSchedule.Ticket = job;
         dbSchedule.ScheduleDate = date;
         db.Schedule.Add(dbSchedule);
      }

      db.SaveChanges();
   }
}

基本上,它会遍历一堆日期并调用一个名为 ConfigureJob 的可等待方法(该方法对 Web 服务进行 HTTP 调用)。

现在,我想调用这个方法。我试过了:

CreateSchedule(allDates);

这将只是无操作并立即退出。我也试过:

Task.Run(() => { CreateSchedule(allDates); }).Wait();

这也是一样的。

看来我必须让CreateSchedule 返回一个Task&lt;T&gt; 或要等待的任务枚举。这里的正确方法是什么?

【问题讨论】:

  • 不要使用 async void,它们适用于事件处理程序。返回一个任务并一直等待它。
  • 您不应使用async void 而应使用async Task。您还应该 awaiting 调用该函数以使其异步。
  • 啊完美!如果异步方法中没有 return 语句,我没有意识到方法只会隐式返回一个 Task 。另外,@RonBeyer - 我不能await 调用CreateSchedule,因为这是在单元测试中调用的,而单元测试不支持async。但是,我可以在 CreateSchedule() 通话中使用 .Wait()。你们中的一个,请随意写一个答案,我会投票/接受。
  • @MikeChristensen 您使用的是哪个版本的 Visual Studio? VS2012 增加了async/await 单元测试支持。许多测试框架都支持异步测试。
  • @RonBeyer - VS2013。当我尝试将测试标记为异步并运行测试时,它只是显示“失败”(没有错误代码、抛出异常、输出中的任何内容等)。需要注意的一点是,我在 [TestInitialize] 方法中调用此异步方法,而不是 [TestMethod] - 不确定这是否有区别..

标签: c# .net async-await


【解决方案1】:

不要使用async void,它旨在用作事件处理程序。相反,您应该返回一个任务。

private async Task CreateSchedule(IEnumerable<DateTime> dates)
{
   // The rest of your code can remain the same.
}

然后在你的消费代码中,你应该一直使用异步语义,所以你应该在一个返回Task的方法中等待结果:

[TestMethod]
public async Task TestScheduler()
{
    // .. Maybe some prep work here ..
    await CreateSchedule(allDates);
    // .. Do Some Assert Checks Here ..
}

【讨论】:

  • 谢谢!我还要指出,我从不支持async[TestInitialize] 方法中调用CreateSchedule。相反,我必须使用:CreateSchedule(allDates).Wait();
  • 出于好奇,您知道 async/await 做什么而常规阻塞方法调用不知道吗?每个人都知道如何使用它们,但我找不到关于它们做什么的任何信息。我发现的示例代码就像任何普通的方法调用一样块。
  • @EdPlunkett 它不会阻塞,它会返回到 await 处的调用函数,并带有代表函数其余部分的 Task。单元测试代码有特殊的东西,在返回的任务完成且没有错误之前不会标记测试完成。
  • @EdPlunkett - 这基本上是编译器的诡计,可以让您不必为异步编程编写各种委托。您只需按照逻辑上有意义的方式编写内容即可。但正如 Scott 所说,await 不会 阻塞线程;该方法立即退出,该方法的其余部分被包装到稍后调用的委托中。
  • @MikeChristensen 这就是我所读到的。我猜是我自己的错误;我试图用它来异步调用 Web 服务而不阻塞 UI 线程。不能让它这样做。没什么大不了的,没有它我也可以写线程。
猜你喜欢
  • 1970-01-01
  • 2017-04-27
  • 1970-01-01
  • 2014-09-13
  • 2011-02-24
  • 2012-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多