如何在异步方法中启动未等待的后台任务?

Dav*_*bin 4 .net c# async-await

我正在努力学习如何在异步方法的世界中执行一些非常长时间运行的后台处理.

使用Stephen Cleary的博客中的词汇,我有兴趣在"承诺任务" 之后启动 "委托await任务".我希望尽快返回承诺的值,并让委托任务在后台继续.

为了处理uned await-ed委托任务中的异常,我将使用在此处描述的模型之后建模的异常处理延续.

public async Task<int> ComplexProcessAsync()
{
  ...
  int firstResult = await FirstStepAsync();

  // THE COMPILER DOESN'T LIKE THIS
  Task.Run(() => VeryLongSecondStepIDontNeedToWaitFor(firstResult)).LogExceptions();

  return firstResult;
}
Run Code Online (Sandbox Code Playgroud)

因为VeryLongSecondStep...()可能需要很多分钟,并且其结果纯粹是通过副作用(例如出现在数据库中的记录)可观察到的,所以我不愿意这样做await.

但正如所指出的,编译器并不喜欢这样.它警告说"Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call."

我可以忽略这个警告,但我觉得我不是以"正确"的方式做这件事.那么,什么正确的方法是什么?

谢谢!

Ste*_*ary 7

我可以忽略这个警告,但我觉得我不是以"正确"的方式做这件事.那么正确的方法是什么?

编译器警告您没有等待该任务.根据我的经验,> 99%的时候编译器是正确的,代码是错误的,因为它缺少了await.因此,这是您知道自己正在做什么并希望危险地生活的罕见情况之一.:)

在这种情况下,您可以将任务显式分配给未使用的变量:

var _ = Task.Run(() => VeryLongSecondStepIDontNeedToWaitFor(firstResult));
Run Code Online (Sandbox Code Playgroud)

编译器足够智能,可以理解您正在使用此变量来消除"丢失等待"警告.

另外,我根本不建议ContinueWith; 在异步世界中,它只是一个更危险的版本await.所以我会写LogExceptions这样的东西:

public static async Task LogExceptions(this Task task)
{
  try
  {
    await task.ConfigureAwait(false);
  }
  catch (Exception ex)
  {
    LogException(ex);
  }
}
Run Code Online (Sandbox Code Playgroud)