【问题标题】:Async/Await - not awaiting the async method [duplicate]异步/等待 - 不等待异步方法 [重复]
【发布时间】:2015-08-11 21:14:05
【问题描述】:

下面是我的代码。编译器发出警告,因为没有等待 AddLog。我不想等待这个电话并想继续执行下一行。如果异常也被消耗,我也不担心。可以忽略警告吗?

public async Task Add()
{
    this.AddLog( "Add executing" );

    // Logic to Add Customer
}

public async Task AddLog( string message )
{
    // Write to DB
}

【问题讨论】:

  • 为什么你不想等待?如果AddLog 方法抛出异常怎么办?你也不想管它?
  • 是的,我不在乎 AddLog 是否抛出异常。我只想继续执行其他代码。
  • 如果它抛出,它可能会关闭您的应用程序。这就是你想要的吗?

标签: async-await


【解决方案1】:

假设您真的想以即发即弃的方式调用 AddLog 方法,那么您有几个选择。

如果按照设计,您希望 AddLog总是 被调用为即发即弃的方法,那么您可以将签名更改为不返回Task.

public async void AddLog( string message ) // change Task to void
{
    // Write to DB
    // WARNING: Make sure that exceptions are handled in here.
}

但是,如果您这样做,您最好确保在 AddLog 方法中正确处理异常。如果任何异常未得到处理,它将使您的进程崩溃。

另一种选择是更改调用AddLog 的方式,以明确说明您不关心Task 何时完成或可能引发的任何异常的意图。您可以通过定义一个空的延续来做到这一点(嗯,几乎是空的。请参阅我在帖子底部的编辑,了解为什么至少阅读 Task.Exception 属性是个好主意)。

// see EDIT for why the Task.Exception property is read here.
this.AddLog("Add executing").ContinueWith(t => { var observed = t.Exception; });

使用任一选项,除非您正在等待您的 Add 方法中没有向我们展示的其他代码,否则将您的 Add 方法定义为 async 不再有任何意义。您可以简单地将其转换为常规同步方法。否则,您将收到另一个警告,告诉您This async method lacks 'await' operators and will run synchronously...

public void Add() // no need for "async Task"
{
    // see EDIT for why the Task.Exception property is read here.
    this.AddLog("Add executing").ContinueWith(t => { var observed = t.Exception; });

    // Logic to Add Customer
}

无论如何,我不会简单地忽略警告。就像有时我们收到警告Use of unassigned local variable 'x' 一样,在我们知道我们的代码没问题的情况下,我们通常不会忽略警告。相反,我们可以将变量显式初始化为null,以明确我们的意图,并使警告消失。同样,您可以使用上述选项之一让编译器更明确地表达您的意图,从而消除警告。

编辑:注意未观察到的异常

我还应该提到,即使使用 ContinueWith 选项,您也可能必须小心来自 AddLog 方法的未处理异常。

根据this article,处理来自任务的未观察到的异常的方式在.NET 4.0 和.NET 4.5 之间发生了变化。因此,如果您仍在运行 .NET 4.0,或者如果您通过配置强制执行 .NET 4.0 异常行为,您将面临这样的风险,即每当任务被 GC 收集并完成时,未处理的异常就会使您的进程崩溃。

为确保这不是问题,您可以调整延续以明确观察异常(如果存在)。你实际上不需要对它做任何事情,你只需要阅读它。这是安全的一种方法:

this.AddLog("Add executing").ContinueWith(t => { var observed = t.Exception; });

我已经更新了我之前的示例以使用更安全的延续版本。

【讨论】:

    【解决方案2】:

    我会让 add() 非异步,因为它不是...然后 task.run on add log

    【讨论】:

    • 为什么会改善这种情况?
    • Var task = this.addlog。然后在方法结束时等待任务。这可能对你更好
    猜你喜欢
    • 2016-07-07
    • 2016-03-25
    • 2017-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-29
    相关资源
    最近更新 更多