C# 在IHTTPassynchandler中同步调用Web服务
我试图调用IHttpAsyncHandler中的Web服务,我发现有这样一个答案 我对答案有疑问。如果有人能帮助我,我将不胜感激 它有C# 在IHTTPassynchandler中同步调用Web服务,c#,web-services,C#,Web Services,我试图调用IHttpAsyncHandler中的Web服务,我发现有这样一个答案 我对答案有疑问。如果有人能帮助我,我将不胜感激 它有 Task webClientDownloadTask = webClientDownloadCompletionSource.Task; 我的问题是 Webclient DownloadCompletionSource与Webclient(客户端)对象无关,因此执行此操作的目的是什么: //获取TCS的任务,以便我们可以附加一些continuation Ta
Task webClientDownloadTask = webClientDownloadCompletionSource.Task;
我的问题是
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)
{
}
}
公共类MyAsyncHandler:IHTTPassynchandler
{
公共IAsyncResult BeginProcessRequest(HttpContext上下文、AsyncCallback cb、object extraData)
{
//注意:这个操作的结果是void,但是TCS需要一些数据类型,所以我们只使用bool
TaskCompletionSource webClientDownloadCompletionSource=新TaskCompletionSource();
WebClient WebClient=新的WebClient()
HttpContext currentHttpContext=HttpContext.Current;
//设置下载完成的事件处理程序
client.DownloadDataCompleted+=(o,e)=>
{
如果(如已取消)
{
//如果取消,则向TCS发送取消信号
//注意:可能不需要这个,因为您没有任何取消操作的方法
webClientDownloadCompletionSource.setCancelled();
}
否则如果(例如错误!=null)
{
//如果出现异常,则向TCS发送异常信号
webClientDownloadCompletionSource.SetException(e.Error);
}
其他的
{
//成功,写下回应
currentHttpContext.Response.ContentType=“text/xml”;
currentHttpContext.Response.OutputStream.Write(e.Result,0,e.Result.Length);
//向已完成的TCS发送信号(我们实际上没有查看bool结果,但这是必需的)
taskCompletionSource.SetResult(true);
}
};
string url=“url\u web\u service\u url”;
//立即开始下载
DownloadDataAsync(新Uri(url));
//获取TCS的任务,以便我们可以附加一些continuation
Task webClientDownloadTask=webClientDownloadCompletionSource.Task;
//工作完成后,务必处置客户
webClientDownloadTask.ContinueWith(
_ =>
{
client.Dispose();
},
TaskContinuationOptions.ExecuteSynchronously);
//如果传入了回调,我们需要在下载工作完成后调用它
如果(cb!=null)
{
webClientDownloadTask.ContinueWith(
webClientDownloadAntecedent=>
{
cb(网络客户端下载先行项);
},
TaskContinuationOptions.ExecuteSynchronously);
}
//将TCS的任务作为IAsyncResult返回
返回webClientDownloadTask;
}
公共无效EndProcessRequest(IAsyncResult结果)
{
//展开任务并等待它,这将传播可能发生的任何异常
((任务)结果)。等待();
}
公共布尔可重用
{
得到
{
return true;//为什么不在这里返回true?您没有状态,它很容易重用!
}
}
公共void ProcessRequest(HttpContext上下文)
{
}
}
查看此项了解其用途。最后还有一个例子
在许多情况下,启用任务来表示
外部异步操作TaskCompletionSource{TResult}
为此目的而提供。它允许创建一个可以
分发给消费者,这些消费者可以使用
这项任务和其他任务一样重要。但是,与大多数任务不同的是
TaskCompletionSource创建的任务的状态受控制
由TaskCompletionSource上的方法显式执行。这使得
完成要传播到的外部异步操作
基本任务。这种分离还确保消费者
无法在不访问相应服务器的情况下转换状态
TaskCompletionSource
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)
{
}
}