在IHttpAsyncHandler中调用WebService Aysnchronously

时间:2016-01-26 01:38:48

标签: c# web-services

我正在尝试在IHttpAsyncHandler中调用WebService,我看到有这样的答案 Using an IHttpAsyncHandler to call a WebService Asynchronously

我对答案有疑问。如果有人能帮助我,我感激不尽。

它有

Task webClientDownloadTask = webClientDownloadCompletionSource.Task;

我的问题是

  1. webClientDownloadCompletionSource与Webclient(客户端)对象无关,因此有什么意义:

    //获取TCS的任务,以便我们可以添加一些延续 任务webClientDownloadTask = webClientDownloadCompletionSource.Task;

  2. 什么是" taskCompletionSource"在这里:

        // Signal the TCS that were done (we don't actually look at the bool result, but it's needed)
        taskCompletionSource.SetResult(true);
    
  3. 为什么我在KeepWith()回调中释放()WebClient,为什么不在设置taskCompletionSource.SetResult(true)之后只处理WEbClient;?

    //完成工作后,务必处理客户端         webClientDownloadTask.ContinueWith(             _ =>             {                 client.Dispose();             },             TaskContinuationOptions.ExecuteSynchronously);

  4. 以下是完整代码:

        public class MyAsyncHandler : IHttpAsyncHandler
    {
        public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
        {
            // NOTE: the result of this operation is void, but TCS requires some data type so we just use bool
            TaskCompletionSource<bool> webClientDownloadCompletionSource = new TaskCompletionSource<bool>();
    
            WebClient webClient = new WebClient())
            HttpContext currentHttpContext = HttpContext.Current;
    
            // Setup the download completed event handler
            client.DownloadDataCompleted += (o, e) =>
            {
                if(e.Cancelled)
                {
                    // If it was canceled, signal the TCS is cacnceled
                    // NOTE: probably don't need this since you have nothing canceling the operation anyway
                    webClientDownloadCompletionSource.SetCanceled();
                }
                else if(e.Error != null)
                {
                    // If there was an exception, signal the TCS with the exception
                    webClientDownloadCompletionSource.SetException(e.Error);
                }
                else
                {
                    // Success, write the response
                    currentHttpContext.Response.ContentType = "text/xml";
                    currentHttpContext.Response.OutputStream.Write(e.Result, 0, e.Result.Length);
    
                    // Signal the TCS that were done (we don't actually look at the bool result, but it's needed)
                    taskCompletionSource.SetResult(true);
                }
            };
    
            string url = "url_web_service_url";
    
            // Kick off the download immediately
            client.DownloadDataAsync(new Uri(url));
    
            // Get the TCS's task so that we can append some continuations
            Task webClientDownloadTask = webClientDownloadCompletionSource.Task;
    
            // Always dispose of the client once the work is completed
            webClientDownloadTask.ContinueWith(
                _ =>
                {
                    client.Dispose();
                },
                TaskContinuationOptions.ExecuteSynchronously);
    
            // If there was a callback passed in, we need to invoke it after the download work has completed
            if(cb != null)
            {
                webClientDownloadTask.ContinueWith(
                   webClientDownloadAntecedent =>
                   {
                       cb(webClientDownloadAntecedent);
                   },
                   TaskContinuationOptions.ExecuteSynchronously);
             }
    
            // Return the TCS's Task as the IAsyncResult
            return webClientDownloadTask;
        }
    
        public void EndProcessRequest(IAsyncResult result)
        {
            // Unwrap the task and wait on it which will propagate any exceptions that might have occurred
            ((Task)result).Wait();
        }
    
        public bool IsReusable
        {
            get 
            { 
                return true; // why not return true here? you have no state, it's easily reusable!
            }
        }
    
        public void ProcessRequest(HttpContext context)
        {
        }
    }
    

1 个答案:

答案 0 :(得分:0)

检查一下,了解它的用途。最后还有一个例子

TaskCompletionSource

  

在许多情况下,启用任务来表示非常有用   外部异步操作。 TaskCompletionSource {TResult} 是   为此目的而提供。它可以创建可以执行的任务   分发给消费者,消费者可以使用   任务与其他任务一样。但是,与大多数任务不同,   由TaskCompletionSource创建的任务的状态受到控制   通过TaskCompletionSource上的方法显式地显示。这使得   完成要传播的外部异步操作   基础任务。分离也确保消费者   没有访问相应的权限就无法转换状态   TaskCompletionSource。