C# 对asmx服务的异步/等待调用
我正在使用一个asmx服务,并在尝试调用它时尝试执行async/Wait 目前我的控制器如下所示C# 对asmx服务的异步/等待调用,c#,web-services,asynchronous,async-await,asmx,C#,Web Services,Asynchronous,Async Await,Asmx,我正在使用一个asmx服务,并在尝试调用它时尝试执行async/Wait 目前我的控制器如下所示 Public ActionResult Index() { var data = _repository.GetDataFromAsmxService(somedata); } //RepositoryClass方法 public List<ObjectToReturn> GetDataFromAsmxService(somedata) { var res = _asmxS
Public ActionResult Index()
{
var data = _repository.GetDataFromAsmxService(somedata);
}
//RepositoryClass方法
public List<ObjectToReturn> GetDataFromAsmxService(somedata)
{
var res = _asmxService.GetReportData(somedata);
var result = process(res);
return result;
}
public List GetDataFromAsmxService(somedata)
{
var res=_asmxService.GetReportData(somedata);
var结果=过程(res);
返回结果;
}
进一步查看生成的refrence.cs文件后,发现存在用于等效调用的void async和onCompleted方法
所以我把它改成了
private void GetReportDataCallBack(object sender, GetReportDataCompletedEventArgs e)
{
var res = e.Result;
var result = process(res);
}
public List<ObjectToReturn> GetDataFromAsmxService(somedata)
{
_asmxService.GetReportDataCompleted +=GetReportDataCallBack;
_asmxService.GetReportDataAsync(somedata);
}
private void GetReportDataCallBack(对象发送方,GetReportDataCompletedEventArgs e)
{
var res=e.结果;
var结果=过程(res);
}
公共列表GetDataFromAsmxService(somedata)
{
_asmxService.GetReportDataCompleted+=GetReportDataCallBack;
_asmxService.GetReportDataAsync(somedata);
}
但是现在回调发生在事件委托上,因此期望返回数据的控制器将无法获取它。
从控制器调用async/Wait并从asmx webservice获取数据的更好方法是什么
来自Refenrece.cs的代码
//生成代码
[System.Web.Services.Protocols.SoapHeaderAttribute("ApiAuthenticationValue")]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://webservice.com/GetReportData", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
[return: System.Xml.Serialization.XmlElementAttribute(Namespace="http://webservice.com/")]
public GetReportDataResponse GetReportData([System.Xml.Serialization.XmlElementAttribute(Namespace="http://webservice.com/")] GetReportDataRequest GetReportDataRequest) {
object[] results = this.Invoke("GetReportData", new object[] {
GetReportDataRequest});
return ((GetReportDataResponse)(results[0]));
}
/// <remarks/>
public void GetReportDataAsync(GetReportDataRequest GetReportDataRequest) {
this.GetReportDataAsync(GetReportDataRequest, null);
}
/// <remarks/>
public void GetReportDataAsync(GetReportDataRequest GetReportDataRequest, object userState) {
if ((this.GetReportDataOperationCompleted == null)) {
this.GetReportDataOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetReportDataOperationCompleted);
}
this.InvokeAsync("GetReportData", new object[] {
GetReportDataRequest}, this.GetReportDataOperationCompleted, userState);
}
private void OnGetReportDataOperationCompleted(object arg) {
if ((this.GetReportDataCompleted != null)) {
System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
this.GetReportDataCompleted(this, new GetReportDataCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
}
}
[System.Web.Services.Protocols.SoapHeaderAttribute(“APAuthenticationValue”)]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute(“http://webservice.com/GetReportData,Use=System.Web.Services.Description.SoapBindingUse.Literal,ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
[返回:System.Xml.Serialization.XmlElementAttribute(命名空间=”http://webservice.com/")]
公共GetReportDataResponse GetReportData([System.Xml.Serialization.XmlElementAttribute(命名空间=”http://webservice.com/“”]GetReportDataRequest(GetReportDataRequest){
object[]results=this.Invoke(“GetReportData”,新对象[]{
GetReportDataRequest});
返回((GetReportDataResponse)(结果[0]);
}
///
public void GetReportDataAsync(GetReportDataRequest GetReportDataRequest){
this.GetReportDataAsync(GetReportDataRequest,null);
}
///
public void GetReportDataAsync(GetReportDataRequest GetReportDataRequest,object userState){
if((this.GetReportDataOperationCompleted==null)){
this.GetReportDataOperationCompleted=new System.Threading.SendOrPostCallback(this.OnGetReportDataOperationCompleted);
}
this.InvokeAsync(“GetReportData”,新对象[]{
GetReportDataRequest},this.GetReportDataOperationCompleted,userState);
}
私有void OnGetReportDataOperationCompleted(对象arg){
如果((this.GetReportDataCompleted!=null)){
System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs=((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
this.GetReportDataCompleted(this,新的GetReportDataCompletedEventArgs(invokeArgs.Results,invokeArgs.Error,invokeArgs.Cancelled,invokeArgs.UserState));
}
}
你所拥有的是一份工作,你想做的是等待它。你可以通过一个
公共异步任务GetDataFromAsmxServiceAsync(GetReportDataRequest somedata)
{
var tcs=new TaskCompletionSource();
_asmxService.GetReportDataCompleted+=GetReportDataCallBack;
_asmxService.GetReportDataAsync(somedata,tcs);//我们传入tcs,以便可以从回调中使用它。
GetReportDataResponse;
尝试
{
res=等待tcs.Task;
}
最后
{
//完成后从处理程序中取消订阅,这样我们就不会泄露消息。
_asmxService.GetReportDataCompleted-=GetReportDataCallBack;
}
var结果=过程(res);
返回结果;
}
私有void GetReportDataCallBack(对象发送方,GetReportDataCompletedEventArgs e)
{
var tcs=(TaskCompletionSource)e.UserState;
如果(如已取消)
{
tcs.trysetconceled();
}
否则如果(例如错误!=null)
{
tcs.TrySetException(即错误);
}
其他的
{
tcs.TrySetResult(e.Result);
}
}
您还需要将控制器更改为异步
public Task<ActionResult> IndexAsync()
{
var data = await _repository.GetDataFromAsmxServiceAsync(somedata);
}
public任务,解释如何从同步MVC代码转换为异步MVC代码,并解释为什么即使Index
现在被称为IndexAsync
,它仍将作为索引的控制器工作。让我们看看存储库的完整方法签名。它确实依赖于它是什么,然后才能以不同的方式使用它。@Cameron public List GetDataFromAsmxService(somedata)能否提供GetReportData
的代码?这是一种服务webmethod,我有参考代码。cs@ScottChamberlain添加了methoddoes异常传播到控制器的ref.cs文件。如果在repositoryYes中抛出异常,则该模式中的异常应像非异步版本一样处理。它们将通过wait在线路上被引发。传播异常的东西是tcs.TrySetException(e.Error)
,当您在GetDataFromAsmxServiceAsync
和IndexAsync
@JMD中等待返回的任务时,会引发从事件内部异步引发的任何异常,task res=_asmxService.GetReportDataAsync(somedata)代码>不编译,GetReportDataAsync
返回void
notTask
。如果它确实返回Task
,则整个代码可以简化为result=process(wait_asmxService.GetReportDataAsync(somedata))代码>TaskCompletionSource的整个要点是将使用事件显示何时完成的somthing转换为使用任务显示何时完成的somthing。有关更多信息,请阅读我答案中关于EAP的第一个链接。@JMD任务版本的实际术语是“”,还有第三种“”。APM是BeginXxxxx(
/EndXxxxxx(I
public Task<ActionResult> IndexAsync()
{
var data = await _repository.GetDataFromAsmxServiceAsync(somedata);
}