假设您真的想以即发即弃的方式调用 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; });
我已经更新了我之前的示例以使用更安全的延续版本。