我正在尝试在IHttpAsyncHandler中调用WebService,我看到有这样的答案 Using an IHttpAsyncHandler to call a WebService Asynchronously
我对答案有疑问。如果有人能帮助我,我感激不尽。
它有
Task webClientDownloadTask = webClientDownloadCompletionSource.Task;
我的问题是
webClientDownloadCompletionSource与Webclient(客户端)对象无关,因此有什么意义:
//获取TCS的任务,以便我们可以添加一些延续 任务webClientDownloadTask = webClientDownloadCompletionSource.Task;
什么是" taskCompletionSource"在这里:
// Signal the TCS that were done (we don't actually look at the bool result, but it's needed)
taskCompletionSource.SetResult(true);
为什么我在KeepWith()回调中释放()WebClient,为什么不在设置taskCompletionSource.SetResult(true)之后只处理WEbClient;?
//完成工作后,务必处理客户端 webClientDownloadTask.ContinueWith( _ => { client.Dispose(); }, TaskContinuationOptions.ExecuteSynchronously);
以下是完整代码:
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)
{
}
}
答案 0 :(得分:0)
检查一下,了解它的用途。最后还有一个例子
在许多情况下,启用任务来表示非常有用 外部异步操作。 TaskCompletionSource {TResult} 是 为此目的而提供。它可以创建可以执行的任务 分发给消费者,消费者可以使用 任务与其他任务一样。但是,与大多数任务不同, 由TaskCompletionSource创建的任务的状态受到控制 通过TaskCompletionSource上的方法显式地显示。这使得 完成要传播的外部异步操作 基础任务。分离也确保消费者 没有访问相应的权限就无法转换状态 TaskCompletionSource。