提交 721ac11a 编写于 作者: J Jason Malinowski

Have AsyncLazy.Request inherit from TaskCompletionSource

We were doing this previously, but in 39815975 had to move away from
it because we needed to hold onto an additional struct. The reason
for that is now gone, so we can go back to the pattern.
上级 ba2e9847
......@@ -520,7 +520,12 @@ private void OnAsynchronousRequestCancelled(object state)
}
}
private sealed class Request
/// <remarks>
/// This inherits from <see cref="TaskCompletionSource{TResult}"/> to avoid allocating two objects when we can just use one.
/// The public surface area of <see cref="TaskCompletionSource{TResult}"/> should probably be avoided in favor of the public
/// methods on this class for correct behavior.
/// </remarks>
private sealed class Request : TaskCompletionSource<T>
{
/// <summary>
/// The <see cref="CancellationToken"/> associated with this request. This field will be initialized before
......@@ -529,20 +534,15 @@ private sealed class Request
private CancellationToken _cancellationToken;
private CancellationTokenRegistration _cancellationTokenRegistration;
private TaskCompletionSource<T> _taskCompletionSource;
public Request()
// We want to always run continuations asynchronously. Running them synchronously could result in deadlocks:
// if we're looping through a bunch of Requests and completing them one by one, and the continuation for the
// first Request was then blocking waiting for a later Request, we would hang. It also could cause performance
// issues. If the first request then consumes a lot of CPU time, we're not letting other Requests complete that
// could use another CPU core at the same time.
public Request() : base(TaskCreationOptions.RunContinuationsAsynchronously)
{
// We want to always run continuations asynchronously. Running them synchronously could result in deadlocks:
// if we're looping through a bunch of Requests and completing them one by one, and the continuation for the
// first Request was then blocking waiting for a later Request, we would hang. It also could cause performance
// issues. If the first request then consumes a lot of CPU time, we're not letting other Requests complete that
// could use another CPU core at the same time.
_taskCompletionSource = new TaskCompletionSource<T>(TaskCreationOptions.RunContinuationsAsynchronously);
}
public Task<T> Task => _taskCompletionSource.Task;
public void RegisterForCancellation(Action<object> callback, CancellationToken cancellationToken)
{
_cancellationToken = cancellationToken;
......@@ -559,11 +559,11 @@ public void CompleteFromTask(Task<T> task)
}
else if (task.IsFaulted)
{
_taskCompletionSource.TrySetException(task.Exception);
this.TrySetException(task.Exception);
}
else
{
_taskCompletionSource.TrySetResult(task.Result);
this.TrySetResult(task.Result);
}
_cancellationTokenRegistration.Dispose();
......@@ -571,8 +571,8 @@ public void CompleteFromTask(Task<T> task)
public void Cancel()
{
_taskCompletionSource.TrySetCanceled(_cancellationToken);
this.TrySetCanceled(_cancellationToken);
}
}
}
}
\ No newline at end of file
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册