//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //------------------------------------------------------------------------------ namespace System.Web.UI { using System; using System.Threading; using System.Threading.Tasks; // Represents an IPageAsyncTask that follows APM (Begin / End) internal sealed class PageAsyncTaskApm : IPageAsyncTask { private readonly BeginEventHandler _beginHandler; private readonly EndEventHandler _endHandler; private readonly object _state; public PageAsyncTaskApm(BeginEventHandler beginHandler, EndEventHandler endHandler, object state) { _beginHandler = beginHandler; _endHandler = endHandler; _state = state; } public async Task ExecuteAsync(object sender, EventArgs e, CancellationToken cancellationToken) { // The CancellationToken is ignored in APM since every call to Begin must be matched by // a call to End, otherwise memory leaks and other badness can occur. // The reason we don't use TaskFactory.FromAsync is that we need the end handler to execute // within the current synchronization context, but FromAsync doesn't make that guarantee. // The callback that marks the TaskCompletionSource as complete can execute synchronously or asynchronously. TaskCompletionSource taskCompletionSource = new TaskCompletionSource(); IAsyncResult asyncResult = _beginHandler(sender, e, _ => { taskCompletionSource.SetResult(null); }, _state); await taskCompletionSource.Task; _endHandler(asyncResult); } } }