-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Add a way to wait for a Task without throwing and without allocating #17148
Comments
Did I open the same issue twice? This is funny. |
You can already do this with an extension method returning custom awaitable/awaiter structs that wrap
But If you do something like this, you need to be careful not to leave the exception unobserved.
|
@brian-reichle this is new idea. But it only works if you want to await the task. Instead, you might want to |
var task = Task.WhenAll(...);
await task.NonObserving(false);
if (task.IsFaulted && IsIgnorable(task.Exception))
{
return null;
}
return task.Result; |
@benaadams you might not want the combined task to end up faulted. Maybe the task is supposed to signal completion, not successful completion. Other code might process that task not expecting any fault. I acknowledge that this is getting more contrived now... |
@GSPP In that case, you can probably use |
@GSPP, it was mostly posed as an alternative to your suggestion to extend In any case, this can still work to reduce the number of throws for multiple async requests, just use it in an async method that sanitizes the result of a single request before aggregating all the tasks. Of course, this won't help much with the number of allocations, but I suspect that aspect might be overrated. If you find you really need to reduce the number of allocations per-request (and still want to use TPL), then you might need to do the combining yourself by awaiting multiple times in a single async method ... but there will probably be easier ways to 'trim the fat'.
|
We need API proposal. Scenario seems useful. |
@GSPP do you want to complete formal API proposal then we can review formally? Docs on the API review process and see Jon's API request for a great example of a strong proposal. The more concrete the proposal is (e.g. has examples of usage, real-world scenarios, fleshed out API), the more discussion it will start and the better the chances of us being able to push the addition through the review process. |
My time is too limited right now to act on this. Just leaving this note here so that others know this is "up for grabs". |
Has this been resolved with ValueTask and IValueTaskSource? |
@benaadams How exactly do they solve the issue of synchronously or asynchronously waiting for a |
Ah, good point, reread; is different issue :) |
This is possible now with ConfigureAwait as of #87067, e.g. task.ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing).GetAwaiter().GetResult(); While it's not the prettiest line of code ever, it gets the job done. I don't see us adding an additional mechanism, so I'm going to close this out. Thanks. |
At the moment there does not seem to be ay direct API that you can use to wait for a task to complete without throwing in case the task completes cancelled or faulted.
This forces using exceptions for control flow:
This is ugly and very slow. Exceptions seem to cost ~0.1ms of CPU time to process.
So if you are writing a port scanner using async IO you will find that you cannot scan more that 10k ports per second because the CPU is pegged from exception processing(!). Also, I don't know if exceptions scale across CPUs. I know that
ExceptionDispatchInfo
uses a global lock internally. So at least some of the processing does not scale at all.It might not be too common to have many faulted tasks. But it is more likely to rely on a greater number of cancelled tasks.
I know of two workarounds:
Both allocate, add overhead and both make it unclear what you want to achieve.
Please add a simpler and faster way to wait for a task to complete regardless of the terminal state it ends up in.
The same problem exists with
await
. There is no direct way to wait for completion without throwing. MaybeConfigureAwait
can be extended with anAwaitOptions
enum that has the valuesIgnoreContext, NoThrow
.The text was updated successfully, but these errors were encountered: