I know that Task.Wait()
block thread in which it is executed.
Do I understand correctly that Task.WaitAsync()
does not do this?
I tried to find information about it but I didn't find anything
CodePudding user response:
WaitAsnync will return a new task that needs to be awaited in turn. It's not used to avoid await
, it's used to allow cancelling a wait for another task.
If you want you await for a task to complete without blocking you'll have to use await
in an async
method, or use ContinueWith
with the continuation code:
async Task MyMethodAsync(Task myTask)
{
...
await myTask;
...
}
This code can await forever and doesn't allow cancelling the wait. If you want to stop waiting after a while you can use Task.WaitAsync
...
try
{
await myTask.WaitAsync(TimeSpan.FromMinute(1));
}
catch(TimeoutException)
{
//Handle the timeout
}
...
Or you may want to cancel awaiting that task if a parent call signals cancellation through a CancellationTokenSource
async Task MyMethod(Task someTask,CancellationToken cancellationToken=default)
{
....
await someTask.WaitAsync(cancellationToken);
...
}
CodePudding user response:
It is non-blocking since it returns a Task
. See the documentation.
public Task WaitAsync(CancellationToken cancellationToken);
public Task WaitAsync(TimeSpan timeout);
public Task WaitAsync(TimeSpan timeout, CancellationToken cancellationToken);
Gets a
Task
that will complete when thisTask
completes, when the specified timeout expires, or when the specifiedCancellationToken
has cancellation requested.
The implementation can be found here:
public static Task WaitAsync(this Task task, int millisecondsTimeout) =>
WaitAsync(task, TimeSpan.FromMilliseconds(millisecondsTimeout), default);
public static Task WaitAsync(this Task task, TimeSpan timeout) =>
WaitAsync(task, timeout, default);
public static Task WaitAsync(this Task task, CancellationToken cancellationToken) =>
WaitAsync(task, Timeout.InfiniteTimeSpan, cancellationToken);
public async static Task WaitAsync(this Task task, TimeSpan timeout, CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<bool>();
using (new Timer(s => ((TaskCompletionSource<bool>)s).TrySetException(new TimeoutException()), tcs, timeout, Timeout.InfiniteTimeSpan))
using (cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).TrySetCanceled(), tcs))
{
await(await Task.WhenAny(task, tcs.Task).ConfigureAwait(false)).ConfigureAwait(false);
}
}
CodePudding user response:
Yes you are right, WaitAsync
will give you a Task
.
What might be helpful for you is, when ever you need to to execute something async in an synchronous method, the common way to do so is:
methodX().GetAwaiter.GetResult()
A little bit more info about this can be found here. Nevertheless it can be also end in a deadlock and the best way is of course to use await
to execute async code and get the result of it.