异步/等待 - 不等待异步方法

时间:2015-08-11 11:19:49

标签: async-await

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

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

    // Logic to Add Customer
}

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

2 个答案:

答案 0 :(得分:2)

假设您真的想以一种即发即弃的方式调用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方法定义为{{1}已不再有任何意义}。您只需将其转换为常规同步方法即可。否则,您将收到另一个警告,告诉您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方法的未处理异常。

根据this article,处理任务中未观察到的异常的方式在.NET 4.0和.NET 4.5之间发生了变化。因此,如果您仍在运行.NET 4.0,或者如果您通过配置强制执行.NET 4.0异常行为,那么当您执行GC收集和最终确定任务时,您将面临未处理异常将使您的流程崩溃的风险。

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

AddLog

我已经更新了上面的示例,以使用更安全的延续版本。

答案 1 :(得分:0)

我会使add()非异步,因为它不是...然后在添加日志上的task.run