Async/await 调用 asmx 服务
Async/await call to asmx service
我正在使用 asmx 服务并尝试在尝试调用它时执行 async/await
目前我的控制器如下图
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;
}
进一步查看生成的 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);
}
但现在回调发生在事件委托上,所以我的控制器期望 return 数据不会得到它。
从控制器调用 async/await 并从 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));
}
}
你拥有的是 Event-Based Asynchronous Pattern (EAP) and what you want to do is wrap that up in a task so you can await it. You do this via a TaskCompletionSource
.
public async Task<List<ObjectToReturn>> GetDataFromAsmxServiceAsync(GetReportDataRequest somedata)
{
var tcs = new TaskCompletionSource<GetReportDataResponse>();
_asmxService.GetReportDataCompleted += GetReportDataCallBack;
_asmxService.GetReportDataAsync(somedata, tcs); //we pass tcs in so it can be used from the callback.
GetReportDataResponse res;
try
{
res = await tcs.Task;
}
finally
{
//unsubscribe from the handler when done so we don't get a leak.
_asmxService.GetReportDataCompleted -= GetReportDataCallBack;
}
var result = process(res);
return result;
}
private void GetReportDataCallBack(object sender, GetReportDataCompletedEventArgs e)
{
var tcs = (TaskCompletionSource<GetReportDataResponse>)e.UserState;
if (e.Cancelled)
{
tcs.TrySetCanceled();
}
else if (e.Error != null)
{
tcs.TrySetException(e.Error);
}
else
{
tcs.TrySetResult(e.Result);
}
}
您还需要将控制器更改为异步
public Task<ActionResult> IndexAsync()
{
var data = await _repository.GetDataFromAsmxServiceAsync(somedata);
}
Here is a good article 解释了如何从同步 MVC 代码转换为异步 MVC 代码,并解释了为什么即使 Index
现在称为 IndexAsync
它仍然可以用作 Index 的控制器。
我正在使用 asmx 服务并尝试在尝试调用它时执行 async/await
目前我的控制器如下图
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;
}
进一步查看生成的 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);
}
但现在回调发生在事件委托上,所以我的控制器期望 return 数据不会得到它。 从控制器调用 async/await 并从 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));
}
}
你拥有的是 Event-Based Asynchronous Pattern (EAP) and what you want to do is wrap that up in a task so you can await it. You do this via a TaskCompletionSource
.
public async Task<List<ObjectToReturn>> GetDataFromAsmxServiceAsync(GetReportDataRequest somedata)
{
var tcs = new TaskCompletionSource<GetReportDataResponse>();
_asmxService.GetReportDataCompleted += GetReportDataCallBack;
_asmxService.GetReportDataAsync(somedata, tcs); //we pass tcs in so it can be used from the callback.
GetReportDataResponse res;
try
{
res = await tcs.Task;
}
finally
{
//unsubscribe from the handler when done so we don't get a leak.
_asmxService.GetReportDataCompleted -= GetReportDataCallBack;
}
var result = process(res);
return result;
}
private void GetReportDataCallBack(object sender, GetReportDataCompletedEventArgs e)
{
var tcs = (TaskCompletionSource<GetReportDataResponse>)e.UserState;
if (e.Cancelled)
{
tcs.TrySetCanceled();
}
else if (e.Error != null)
{
tcs.TrySetException(e.Error);
}
else
{
tcs.TrySetResult(e.Result);
}
}
您还需要将控制器更改为异步
public Task<ActionResult> IndexAsync()
{
var data = await _repository.GetDataFromAsmxServiceAsync(somedata);
}
Here is a good article 解释了如何从同步 MVC 代码转换为异步 MVC 代码,并解释了为什么即使 Index
现在称为 IndexAsync
它仍然可以用作 Index 的控制器。