【问题标题】:Is "await" keyword compulsory with async methods? [duplicate]异步方法是否必须使用“await”关键字? [复制]
【发布时间】:2017-03-14 15:59:00
【问题描述】:

我有以下方法:

async Task A()
{
    HttpClient client = new HttpClient();
    string response = await client.GetStringAsync("http://msdn.microsoft.com");        
}

async Task B()
{
    HttpClient client = new HttpClient();
    string response = await client.GetStringAsync("http://google.com");
}

即调用远程api,处理响应,不返回任何内容。

我将通过一个常用的方法这样调用它:

protected void Page_Load(object sender, EventArgs e)
{
    A();
    B();

    // Do further task after this which is not dependent on response of A or B
}

编译器对 A 和 B 方法给出以下警告:

因为没有等待这个调用,所以执行当前方法 在呼叫完成之前继续。考虑应用“等待” 调用结果的运算符。

我不需要来自 A 或 B 方法的任何响应,所以我想在 A() 和 B() 前面省略“await”关键字,因为我想在 A 和 B 调用之后执行代码已经写了注释“//在此之后执行不依赖于 A 或 B 响应的进一步任务”而不等待 A 或 B 响应。

我可以忽略编译器警告吗?

我是否在滥用 API?

由于 HttpClient.GetStringAsync 需要它,我无法删除 A 和 B 方法上的异步运算符。

编辑

我去了这个链接 https://softwareengineering.stackexchange.com/questions/331353/does-omitting-await-keyword-once-in-the-call-stack-break-the-asynchronous-behavi

发现如下评论:

“当您不等待异步方法时,它等效于调用 Task.Run(()=>A())。”

这是真的吗?

【问题讨论】:

  • await Task.Run(()=>{A();B();});
  • 你在用response 对象做什么?如果调用AB 之后的代码不需要AB 来完成,那么你的方式很好。
  • 为什么在您的线路中需要“等待”?我不希望这两种方法得到任何回应。
  • 如果您想要的是一劳永逸,您可以放心地忽略大多数情况下的警告(ASP.NET 除外)。一些库,比如 Microsoft.VisualStudio.Threading,甚至提供了帮助来抑制这些警告:msdn.microsoft.com/en-us/library/…
  • 已经有很多“c# fire-and-forget”问题了...请确保edit 发布您的研究结果 - 否则人们可能会认为您甚至没有尝试并否决这个问题。

标签: c# asp.net .net asynchronous async-await


【解决方案1】:

基本上await 确保Task 完成它的执行。在没有await 的情况下运行async 方法就像只是在没有监控其进度和结果的情况下启动Task

例如,在 ASP.Net 环境中,如果任务从请求线程等启动,可能会导致任务中止。

【讨论】:

  • “在没有等待的情况下运行异步方法就像只是在没有监控它的进度和结果的情况下启动任务”我对此没有任何问题,即没有监控它的进度和结果,但可以保证代码将执行或将执行如果我在调用它时不应用该 await 关键字,则会在两者之间中断/丢失。
  • @Raghav - 如果你不关心他们的进度或结果,你也可以用空的方法体替换方法体,或者完全删除方法调用。
  • @Damien_The_Unbeliever 我确实关心我在 A 和 B 中编写的代码的完成,尽管我不关心这些方法返回什么。由于我是从 ASP.NET 页面加载调用它,我必须在 A 和 B 前面应用 await 以保证其完成,并且省略 await 会导致中止这些方法(没有 await 关键字),对吧?
【解决方案2】:

如果您想要“一劳永逸”,您可以放心地忽略大多数情况下的警告(例如 ASP.NET 除外)。一些库,比如 Microsoft.VisualStudio.Threading,甚至提供了帮助来抑制这些警告:https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.threading.tplextensions.forget.aspx

你可以这样使用它:

// Forget doesn't actually do anything internally. 
// It's an empty extension method you use to prove that you actually want the task to be
// fire and forget
A().Forget();
B().Forget();

如果您在同步上下文中执行并且该方法在内部执行await 而没有ConfigureAwait(false),您也可能会遇到一些奇怪的行为。这就是在库代码中应始终使用.ConfigureAwait(false) 的原因之一。


关于你问题的第二部分:

“当您不等待异步方法时,它等效于调用 Task.Run(()=>A())。”

这是真的吗?

错了。至少有两个主要区别:

  1. 当使用async 方法时,第一个await 之前的部分将在调用者线程中同步执行。例如:

    public async Task DoSomething()
    {
        Thread.Sleep(1000); // Will execute in the caller thread
        await SomeExternalResource();
        Thread.Sleep(1000); // Will execute in the continuation
    }
    

    这里,如果你直接调用该方法,调用者线程将至少在 1 秒内被阻塞(至少,因为有可能继续在同一个线程中执行)。如果使用Task.Run,整个方法会在线程池上执行,不会阻塞调用者线程。

  2. 使用Task.Run 执行方法时不会流过当前同步上下文,这在某些情况下会显着改变行为

【讨论】:

  • @Itsik 我看不出.ConfigureAwait(false) 会如何导致死锁。你能详细说明一下吗?
  • 在外部调用中使用 ConfigureAwait 对嵌套的内部等待没有任何作用
  • @KevinGosse 对不起,你是对的,不是死锁,相反!但在客户端代码中,由于同步上下文已更改,他可能无法更新 UI。
  • 感谢@KevinGosse 回复我的编辑。
  • @KevinGosse 我正在阅读此stackoverflow.com/questions/29577652/… 并发现来自 Stephan 的回复“在 ASP.NET 上,如果您像这样开始独立工作(即与 HTTP 请求无关的工作),那么这项工作可能会在你不知情的情况下中止。”该评论再次让我陷入困境,A 或 B 方法是否会完成。
【解决方案3】:

更新:Fire and Forget in ASP.NET

在您的代码中,在方法 AB 完成之前执行的 Do further task after this 不依赖于 A 或 B 的响应部分(除非这些方法非常快)。

当您使用await 并且该方法命中该行时,它会向调用者返回Task,并且调用者继续执行第二行(在您的情况下为B),因为B 执行相同的操作,然后执行调用这两个方法后的部分。

旁注:

每个使用await 关键字的方法都应该标记为异步,这是为了向后比较。然而,编译器只是警告你,你没有在等待调用者的结果,这在许多情况下对初学者来说是一个很好的警告。

【讨论】:

    【解决方案4】:

    如果 A 和 B 的执行与 Page_Load 的其余流程异步,则您不必await 它们。

    这里给出的另一个选项是向阅读您的代码的其他人表明您正在明确地忽略此警告,是用#pragma disable 包装它

    #pragma warning disable warning-list  
    
    A();
    B();
    
    #pragma warning restore warning-list 
    

    【讨论】:

      猜你喜欢
      • 2018-05-15
      • 2012-12-06
      • 1970-01-01
      • 2017-11-06
      • 2019-10-09
      • 2017-01-12
      • 1970-01-01
      • 2021-09-17
      • 2013-06-11
      相关资源
      最近更新 更多