-
Notifications
You must be signed in to change notification settings - Fork 128
Open
Description
The ServiceExtensions.TimeoutAfter
extension method throws a NullReferenceException
if cancellation occurs. The exception occurs because the extension attempts to throw an Exception
that is null
:
public static async Task<TResult> TimeoutAfter<TResult>(this Task<TResult> task, TimeSpan timeout, CancellationToken token)
{
var t = await Task.WhenAny(task, Task.Delay(timeout, token)).ConfigureAwait(false);
if (task != t)
{
if (!t.IsCanceled)
{
throw new TimeoutException($"Task timed out after {timeout}");
}
// Error is here: t.Exception is always null if the Task.Delay task was cancelled
throw t.Exception!;
}
return await task.ConfigureAwait(false);
}
Given that the only two possible states for the Task.Delay
call if it completes first are completed and cancelled, would recommend changing the implementation to:
public static async Task<TResult> TimeoutAfter<TResult>(this Task<TResult> task, TimeSpan timeout, CancellationToken token)
{
var t = await Task.WhenAny(task, Task.Delay(timeout, token)).ConfigureAwait(false);
if (task != t)
{
if (t.IsCanceled)
{
throw new OperationCanceledException(token);
}
throw new TimeoutException($"Task timed out after {timeout}");
}
return await task.ConfigureAwait(false);
}
Metadata
Metadata
Assignees
Labels
No labels