Hier ist eine Low-Level-Implementierung eines WaitAsync
Methode, die sowohl eine Zeitüberschreitung als auch eine CancellationToken
und überträgt im Falle einer Ausnahme alle Fehler des Task<T>
und nicht nur den ersten Fehler:
public static Task<TResult> WaitAsync<TResult>(this Task<TResult> task,
TimeSpan timeout, CancellationToken cancellationToken = default)
{
if (task == null) throw new ArgumentNullException(nameof(task));
if (timeout < TimeSpan.Zero && timeout != Timeout.InfiniteTimeSpan)
throw new ArgumentOutOfRangeException(nameof(timeout));
var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
cts.CancelAfter(timeout);
return task
.ContinueWith(_ => { }, cts.Token,
TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default)
.ContinueWith(continuation =>
{
cts.Dispose();
if (task.IsCompleted) return task;
cancellationToken.ThrowIfCancellationRequested();
if (continuation.IsCanceled) throw new TimeoutException();
return task;
}, TaskScheduler.Default).Unwrap();
}
A TimeoutException
wird ausgelöst, wenn die Zeitüberschreitung vor Beendigung der task
.
Ehrlich gesagt ist die Weitergabe aller Fehler in diesem Fall nicht wirklich eine wertsteigernde Funktion. Der Grund dafür ist, dass wenn Sie die WaitAsync
wie diese: await someTask.WaitAsync(timeout)
werden alle zusätzlichen Fehler von der Software geschluckt. await
Operator, der absichtlich nur die erste Ausnahme der erwarteten Aufgabe weitergibt. Und es macht nicht viel Sinn, die WaitAsync
Aufgabe in einer Variablen zu speichern und sie innerhalb der catch
Block, denn Sie haben bereits den someTask
zur Verfügung, und Sie könnten dies stattdessen untersuchen.