火和忘记的方法

相关的这个答案 ,

如果我确实想要“消除并忘记”一个返回任务的方法,并且(为了简单起见),让我们假设该方法不会抛出任何exception。 我可以使用答案中列出的扩展方法:

public static void Forget(this Task task) { } 

使用这种方法,如果Task存在导致抛出exception的错误,那么当抛出exceptionexception时,exception将被吞下并且不被注意。

问题:在这种情况下,扩展方法的forms不是更合适吗?

 public static async void Forget(this Task task) { await task; } 

所以编程错误会引发exception并升级(通常会导致进程中断)。

在预期(和可忽略)exception的方法中,这个方法需要变得更精细(作为一个旁白,关于如何构build一个可以接受和可忽略的exceptiontypes列表的方法的任何build议? )

这取决于你想要的语义。 如果你想确保例外被注意到,那么是的,你可以await任务。 但在这种情况下,这并不是真正的“火和遗忘”。

一个真正的“火和遗忘” – 在你不关心什么时候完成或者成功完成还是错误的意义上 – 是非常罕见的。

编辑:

为了处理exception:

 public static async void Forget(this Task task, params Type[] acceptableExceptions) { try { await task.ConfigureAwait(false); } catch (Exception ex) { // TODO: consider whether derived types are also acceptable. if (!acceptableExceptions.Contains(ex.GetType())) throw; } } 

请注意,我build议使用await而不是ContinueWithContinueWith 有一个令人惊讶的默认调度程序 (如我的博客中所述), Task.Exception将实际的exception包装在一个AggregateException ,使得error handling代码更加麻烦。

是的,如果你对这个任务是否抛出exception感兴趣,那么你需要await结果,但是反过来说,这几乎是“火与忘记 ”的目的。

在你想知道发生了什么事情的情况下,推荐的做法是使用一个延续例如

 public static void ForgetOrThrow(this Task task) { task.ContinueWith((t) => { Console.WriteLine(t.Exception); }, TaskContinuationOptions.OnlyOnFaulted); } 

在链接问题中,我最初想在以下上下文中使用static void Forget(this Task task)

 var task = DoWorkAsync(); QueueAsync(task).Forget(); // ... async Task QueueAsync(Task task) { // keep failed/cancelled tasks in the list // they will be observed outside _pendingTasks.Add(task); await task; _pendingTasks.Remove(tasks) } 

它看起来很棒,但是后来我意识到_pendingTasks.Add / _pendingTasks.Remove可能抛出的致命exception将被_pendingTasks.Remove并丢失,这是不好的。

所以我只是把QueueTask作为一个async void方法,它本质上是:

 var task = DoWorkAsync(); QueueAsync(task); // ... async void QueueAsync(Task task) { // keep failed/cancelled tasks in the list // they will be observed outside _pendingTasks.Add(task); try { await task; } catch { return; } _pendingTasks.Remove(tasks) } 

就像我不喜欢空的catch {} ,我认为这是有道理的。

在这种情况下,保持async Task QueueAsync()和使用async void Forget(this Task task)像你提出的将是在矫枉过正,国际海事组织。