火和忘记的方法
相关的这个答案 ,
如果我确实想要“消除并忘记”一个返回任务的方法,并且(为了简单起见),让我们假设该方法不会抛出任何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
而不是ContinueWith
。 ContinueWith
有一个令人惊讶的默认调度程序 (如我的博客中所述), 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)
像你提出的将是在矫枉过正,国际海事组织。
- 在方法名称中使用“asynchronous”后缀取决于是否使用“asynchronous”修饰符?
- 你必须把Task.Run放在一个方法来使其asynchronous?
- 等待一个完成的任务相同的task.Result?
- 我将如何同步运行asynchronous任务<T>方法?
- C#5asynchronous/等待 – 它是*并发*?
- 为什么我会打扰使用Task.ConfigureAwait(continueOnCapturedContext:false);
- 无法隐式转换来自任务<>的types
- 在.NET 4.0中创build一个可以与.NET 4.5中的“await”一起使用的asynchronous方法
- 当我使用async / awaitfunction时,Angular UI路由器不处理parsing函数?