Task.WaitAsync与Task.Wait的区别

4

我知道Task.Wait()会阻塞它所在的线程。

那么,我是否正确理解Task.WaitAsync()不会这样做?

我试图找到相关信息,但没有找到任何内容。


Task.WaitAsync() 在你想要根据超时时间来取消 Task 并且不阻塞执行时非常有用。 - undefined
2个回答

8

WaitAsync 将返回一个新的需要依次等待的任务。它不是用来避免await,而是用于允许取消等待另一个任务。

如果你想要等待一个任务完成而不阻塞,你将需要在一个async方法中使用await,或者使用ContinueWith与继续代码:

async Task MyMethodAsync(Task myTask)
{
   ...
   await myTask;
   ...
}

这段代码可能会一直等待下去,而且无法取消等待。如果你想在一段时间后停止等待,可以使用 Task.WaitAsync
...
try
{
    await myTask.WaitAsync(TimeSpan.FromMinute(1));
}
catch(TimeoutException)
{
    //Handle the timeout
}
...

或者,如果父调用通过 CancellationTokenSource 发出取消信号,您可能希望取消等待该任务。

async Task MyMethod(Task someTask,CancellationToken cancellationToken=default)
{
   ....
   await someTask.WaitAsync(cancellationToken);
   ...
}

6

它是非阻塞的,因为它返回一个Task。请查看文档

public Task WaitAsync(CancellationToken cancellationToken);
public Task WaitAsync(TimeSpan timeout);
public Task WaitAsync(TimeSpan timeout, CancellationToken cancellationToken);

获取一个Task,该任务将在此Task完成、指定的超时时间到期或指定的CancellationToken请求取消时完成。

实现可在此处找到:

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);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接