.NET 6中使用WaitAsync替代Task.WhenAny超时实现的差异问询
Task.WhenAny + Task.Delay and WaitAsync Timeout Implementations Great question! Let's break down the important differences between these two approaches that you might have missed:
Exception Propagation for the Original Task
Your originalTask.WhenAnycode doesn't automatically propagate exceptions from thesendingtask. Even ifsendingfails with an exception,await Task.WhenAnywill just return the failed task, and your code will cancel the delay but won't throw the exception unless you explicitlyawait sendingorawait resultTaskafterward.In contrast,
await sending.WaitAsync(...)behaves exactly like directly awaitingsending—ifsendingthrows an exception, it will be propagated immediately to yourtryblock, which you'll need to handle (either with an additionalcatchclause or let it bubble up).Automatic vs. Manual Delay Task Cleanup
Your original code uses aCancellationTokenSourcewrapped in ausingblock to explicitly cancel theTask.Delayoncesendingcompletes. This ensures the delay task doesn't linger unnecessarily.The
WaitAsyncmethod handles this cleanup automatically under the hood: it creates an internal cancellation mechanism that cancels the timeout delay as soon as the original task completes, so you don't need to manage aCancellationTokenSourceyourself. This makes theWaitAsyncversion more concise and less error-prone.Timeout Trigger Behavior
In the original code, when the timeout hits, you immediately call_webSocket.Abort()without throwing aTimeoutException. TheWaitAsyncapproach, however, throws aTimeoutExceptionthat you have to catch to trigger the abort. This is a behavioral difference in how you signal a timeout condition—one uses explicit branching, the other uses exception handling.Potential for Unobserved Exceptions (Edge Case)
If you forget toawaitthesendingtask after theTask.WhenAnycheck in your original code, any exception fromsendingcould become an unobserved exception (though in modern .NET, unobserved exceptions are logged rather than crashing the process). WithWaitAsync, since you're directly awaiting the combined operation, exceptions fromsendingare always observed and propagated.
Overall, the WaitAsync version is more idiomatic for .NET 6+ and reduces boilerplate, but you need to account for the exception propagation difference—your original code silently ignores sending exceptions unless you add code to handle them, while WaitAsync will bubble them up immediately.
内容的提问来源于stack exchange,提问作者nop

