in src/Microsoft.Azure.Relay/Common/TaskEx.cs [309:355]
public static IAsyncResult ToAsyncResult<TResult>(this Task<TResult> task, AsyncCallback callback, object state, bool executeSynchronously = false)
{
// Tasks ALWAYS report IAsyncResult.CompletedSynchronously = false. This can lead to StackOverflow problems
// when interoping with normal IAsyncResult patterns because if IAsyncResult.CompletedSynchronously == false then
// it's supposed to be 'safe' to invoke continuations from the AsyncCallback. This isn't necessarily true
// with Tasks, so in order to break the stack overflow chain don't pass the TaskContinuationOptions.ExecuteSynchronously
// flag. However, this comes with a performance hit. If we have a task that is not completed, it's safe to use
// the ExecuteSynchronously flag since we know the task had to complete asynchronously (as opposed to lying to us).
var continuationOptions = task.IsCompleted || !executeSynchronously ? TaskContinuationOptions.None : TaskContinuationOptions.ExecuteSynchronously;
if (task.AsyncState == state)
{
if (callback != null)
{
task.ContinueWith(
t => callback(task),
continuationOptions);
}
return task;
}
var tcs = new TaskCompletionSource<TResult>(state);
task.ContinueWith(
(t, s) =>
{
var tcsPtr = (TaskCompletionSource<TResult>)s;
if (t.IsFaulted)
{
tcsPtr.TrySetException(t.Exception.InnerExceptions);
}
else if (t.IsCanceled)
{
tcsPtr.TrySetCanceled();
}
else
{
tcsPtr.TrySetResult(t.Result);
}
callback?.Invoke(tcsPtr.Task);
},
tcs,
continuationOptions);
return tcs.Task;
}