private static bool TryBlockingAwait(Type awaitableType, object invocationResult, out object result) { // https://github.com/dotnet/csharplang/blob/master/spec/expressions.md#runtime-evaluation-of-await-expressions var accessors = AwaitableApiAccessors.TryCreate(awaitableType); if (accessors == null) { result = null; return(false); } var awaiter = accessors.GetAwaiter(invocationResult); if (!accessors.IsCompleted(awaiter)) { using (var mres = new ManualResetEventSlim()) { accessors.OnCompleted(awaiter, mres.Set); mres.Wait(); } } result = accessors.GetResult(awaiter); return(true); }
/// <summary> /// If a delegate is created by the end user, <see cref="IsAwaitable(Delegate)"/> must be used instead. /// </summary> public static bool IsAwaitable(MethodInfo methodWithoutEndUserDelegate) { if (methodWithoutEndUserDelegate == null) { throw new ArgumentNullException(nameof(methodWithoutEndUserDelegate)); } // May be different from both @endUserDelegate.Method.ReturnType and invocationResult.GetType(). // Delegate return type is what we need to care about. var awaitableType = methodWithoutEndUserDelegate.ReturnType; return(AwaitableApiAccessors.TryCreate(awaitableType) != null); }
/// <summary> /// If a delegate is created by the end user, <see cref="IsAwaitable(Delegate)"/> must be used instead. /// </summary> public static Type GetAwaitableResultType(MethodInfo methodWithoutEndUserDelegate) { if (methodWithoutEndUserDelegate == null) { throw new ArgumentNullException(nameof(methodWithoutEndUserDelegate)); } // May be different from both @endUserDelegate.Method.ReturnType and invocationResult.GetType(). // Delegate return type is what we need to care about. var awaitableType = methodWithoutEndUserDelegate.ReturnType; var accessors = AwaitableApiAccessors.TryCreate(awaitableType); if (accessors == null) { throw new InvalidOperationException($"{awaitableType} is not awaitable."); } return(accessors.ResultType); }