C# 如何在不等待完成的情况下启动异步方法?

And*_*uin 25 c# asynchronous

有时我需要启动一个工作非常缓慢的异步工作。我不在乎那份工作是否成功,我需要继续处理我当前的线程。

就像有时我需要发送一封电子邮件或短信,但工作速度很慢。我需要尽快回复网络客户端,所以我不想这样做await

我用谷歌搜索了这个问题,有些文章建议我这样写:

// This method has to be async
public async Task<Response> SomeHTTPAction()
{
    // Some logic...
    // ...

    // Send an Email but don't care if it successfully sent.
    Task.Run(() =>  _emailService.SendEmailAsync());
    return MyRespond();
}
Run Code Online (Sandbox Code Playgroud)

或者像这样:

// This method has to be async
public async Task<Response> SomeHTTPAction()
{
    // Some logic...
    // ...

    // Send an Email but don't care if it successfully sent.
    Task.Factory.StartNew(() =>  _emailService.SendEmailAsync());
    return MyRespond();
}
Run Code Online (Sandbox Code Playgroud)

会有警告说: before the call is completed. Consider applying the 'await' operator to the result of the call.

那如果我真的await编辑了呢?在 C# 中“触发并忘记”的最佳实践是什么,只需调用异步方法而不等待其完成?

Cor*_*lis 20

如果你真的只想开火然后忘记。只是不要调用 use await。

// It is a good idea to add CancellationTokens
var asyncProcedure = SomeHTTPAction(cancellationToken).ConfigureAwait(false);

// Or If not simply do:
var asyncProcedure = SomeHTTPAction().ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

如果您想稍后使用结果输出,它会变得更加棘手。但如果它真的很火,忘记了上面的应该工作

取消令牌允许中断和取消过程。如果您正在使用 Cancellation 令牌,您将需要在从检索直接到调用方法的任何地方使用它(Turtles 一直向下)。

我以前是用来ConfigureAwait(false)防止死锁的。在这里了解更多信息

  • *“我使用`ConfigureAwait(false)`来防止死锁。”* -- `ConfigureAwait`方法配置`await`。如果你不“await”它,那么它绝对没有效果。我不会阻止任何死锁,因为一开始就没有发生死锁的风险。 (2认同)

小智 12

单独丢弃是避免此警告的最佳方法。

_ = Task.Run(() =>  _emailService.SendEmailAsync());
Run Code Online (Sandbox Code Playgroud)

丢弃是虚拟变量,可用于忽略异步操作返回的 Task 对象。

https://docs.microsoft.com/en-us/dotnet/csharp/discards#a-standalone-discard


MrM*_*vin 10

如果您需要async在函数中使用,您还可以使用丢弃变量并且不要使用await。如果您有多个异步函数调用但不需要等待所有异步函数调用,这也很有用。

public async function(){
    var tmp = await asyncfunction();
    ...
    _ = _httpClient.PutAsync(url, content);
    ...
}
Run Code Online (Sandbox Code Playgroud)


Jaw*_*ngh 5

正如Amadan在评论中所说,您需要从函数中删除 async。然后它会停止给你警告。

// This method has to be async
public Response SomeHTTPAction()
{
     // Some logic...
     // ...
     // Send an Email but don't care if it successfully sent.
     Task.Factory.StartNew(() =>  _emailService.SendEmailAsync());
     return MyRespond();
}
Run Code Online (Sandbox Code Playgroud)

并且Task.Factory.StartNew(() => _emailService.SendEmailAsync());确实会在一个新线程上工作。