79 lines
3.2 KiB
C#
79 lines
3.2 KiB
C#
|
//------------------------------------------------------------------------------
|
|||
|
// <copyright file="WithinCancellableCallbackTaskAwaitable.cs" company="Microsoft">
|
|||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|||
|
// </copyright>
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
|
|||
|
namespace System.Web.Util {
|
|||
|
using System;
|
|||
|
using System.Runtime.CompilerServices;
|
|||
|
using System.Security.Permissions;
|
|||
|
using System.Threading;
|
|||
|
using System.Threading.Tasks;
|
|||
|
|
|||
|
// An awaitable type that invokes a continuation callback under a call to HttpContext.InvokeCancellableCallback.
|
|||
|
// This type is for compiler use; the ASP.NET runtime is not expected to call into these APIs directly.
|
|||
|
internal struct WithinCancellableCallbackTaskAwaitable {
|
|||
|
|
|||
|
internal static readonly WithinCancellableCallbackTaskAwaitable Completed = new WithinCancellableCallbackTaskAwaitable(null, ((Task)Task.FromResult((object)null)).GetAwaiter());
|
|||
|
|
|||
|
private readonly WithinCancellableCallbackTaskAwaiter _awaiter;
|
|||
|
|
|||
|
public WithinCancellableCallbackTaskAwaitable(HttpContext context, TaskAwaiter innerAwaiter) {
|
|||
|
_awaiter = new WithinCancellableCallbackTaskAwaiter(context, innerAwaiter);
|
|||
|
}
|
|||
|
|
|||
|
public WithinCancellableCallbackTaskAwaiter GetAwaiter() {
|
|||
|
return _awaiter;
|
|||
|
}
|
|||
|
|
|||
|
// The awaiter type that backs WithinCancellableCallbackTaskAwaitable.
|
|||
|
internal struct WithinCancellableCallbackTaskAwaiter : ICriticalNotifyCompletion {
|
|||
|
|
|||
|
private static readonly WaitCallback _shunt = state => ((Action)state)();
|
|||
|
|
|||
|
private readonly HttpContext _context;
|
|||
|
private readonly TaskAwaiter _innerAwaiter;
|
|||
|
|
|||
|
internal WithinCancellableCallbackTaskAwaiter(HttpContext context, TaskAwaiter innerAwaiter) {
|
|||
|
_context = context;
|
|||
|
_innerAwaiter = innerAwaiter;
|
|||
|
}
|
|||
|
|
|||
|
public bool IsCompleted {
|
|||
|
get { return _innerAwaiter.IsCompleted; }
|
|||
|
}
|
|||
|
|
|||
|
public void GetResult() {
|
|||
|
_innerAwaiter.GetResult();
|
|||
|
|
|||
|
// If Response.End was called, need to observe it here.
|
|||
|
HttpContext context = _context;
|
|||
|
if (context != null) {
|
|||
|
context.Response.ObserveResponseEndCalled();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void OnCompleted(Action continuation) {
|
|||
|
Action wrappedContinuation = WrapContinuation(continuation);
|
|||
|
_innerAwaiter.OnCompleted(wrappedContinuation);
|
|||
|
}
|
|||
|
|
|||
|
[SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)] // equivalent of [SecurityCritical]
|
|||
|
public void UnsafeOnCompleted(Action continuation) {
|
|||
|
Action wrappedContinuation = WrapContinuation(continuation);
|
|||
|
_innerAwaiter.UnsafeOnCompleted(wrappedContinuation);
|
|||
|
}
|
|||
|
|
|||
|
private Action WrapContinuation(Action continuation) {
|
|||
|
HttpContext context = _context;
|
|||
|
return (context != null)
|
|||
|
? () => context.InvokeCancellableCallback(_shunt, continuation)
|
|||
|
: continuation;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|