c# – ASP中的异步Web服务. NET MVC
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – ASP中的异步Web服务. NET MVC,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4123字,纯文字阅读大概需要6分钟。
内容图文
![c# – ASP中的异步Web服务. NET MVC](/upload/InfoBanner/zyjiaocheng/794/fca10b7d89fa43d187203aa99b0369dd.jpg)
我正在编写一个ASP.NET MVC 5应用程序,其中包括使用Web服务来获取/处理一些数据.
该应用程序的数据流如下:MVC Action – >服务B – > ExtSvc是Web服务的异步包装器
这里有些例子:
public class ExtSvc
{
//Convert Event based async pattern to task based async pattern:
private Task<Response> ProcessExtRequestAsync(Request request)
{
TaskCompletionSource<Response> taskCompletionSource =
AsyncServiceClientHelpers.CreateSource<Response>(request);
ProcessRequestCompletedEventHandler handler = null;
handler =
(sender, e) =>
AsyncServiceClientHelpers.TransferCompletion(
taskCompletionSource,
e,
() => e.Result,
() => this.Service.ProcessRequestCompleted -= handler);
this.Service.ProcessRequestCompleted += handler;
try
{
this.Service.ProcessRequestAsync(request, taskCompletionSource);
}
catch (Exception)
{
this.Service.ProcessRequestCompleted -= handler;
taskCompletionSource.TrySetCanceled();
throw;
}
return taskCompletionSource.Task;
}
//Usage:
public async Task<Response> UpdateRequest(some arguments)
{
//Validate arguments and create a Request object
var response = await this.ProcessExtRequestAsync(request)
.ConfigureAwait(false);
return response;
}
}
B类是以同步方式使用ExtSvc的类
public class B
{
public ExtSvc service {get; set;}
public Response Update(arguments)
{
//some logic
var result = this.ExtSvc.UpdateRequest(arguments).Result;
//some logic
return result
}
}
最后是MVC动作(同步)
public ActionResult GetResponse(int id)
{
//some logic
B.Update(id);
//some logic
return View(...);
}
所描述的流程会引发错误
A first chance exception of type ‘System.InvalidOperationException’
occurred in System.Web.dllAdditional information: An asynchronous operation cannot be started at
this time. Asynchronous operations may only be started within an
asynchronous handler or module or during certain events in the Page
lifecycle. If this exception occurred while executing a Page, ensure
that the Page is marked <%@ Page Async=”true” %>. This exception may
also indicate an attempt to call an “async void” method, which is
generally unsupported within ASP.NET request processing. Instead, the
asynchronous method should return a Task, and the caller should await
it.
在ExtSvc的以下行:this.Service.ProcessRequestAsync(request,taskCompletionSource); ProcessRequestAsync是一个void方法
所以它对应于:
This exception may
also indicate an attempt to call an “async void” method, which is
generally unsupported within ASP.NET request processing
我知道将GetResponse MVC操作转换为异步(通过使用async / await)并将实际使用ExtSvc的B类转换为异步解决了这个问题.
但我的问题是:
如果我不能改变B类的签名(因为它实现了一个接口)来返回Task< Response>而不是响应它基本上意味着我不能使用async / await,所以如何解决这个问题?
解决方法:
ProcessRequestAsync是void但它不是async void.看起来它是一个EBAP API. EBAP组件generally use AsyncOperationManager/AsyncOperation,反过来do use SynchronizationContext to notify the underlying platform of the asynchronous operation(最后一个链接是我在SynchronizationContext上的MSDN文章).
您看到的异常是因为ASP.NET看到该通知(异步操作开始)并说“哇,那里,家伙.你是同步处理程序!没有异步你!”
动手,最好的方法是使所有方法异步,应该是异步的.这意味着B.Update应该是B.UpdateAsync.好的,所以有一个接口IB.Update – 只需将接口更改为IB.UpdateAsync.然后你一直是异步,代码很干净.
否则,你将不得不考虑黑客攻击.您可以使用Task.Run作为@neleus建议 – 这是避免ASP.NET SynchronizationContext的一种方式,因此它不会“看到”异步操作开始 – 但请注意“环境上下文”,如HttpContext.Current和页面文化是丢失.或者,您可以(暂时)将新的SynchronizationContext()安装到请求线程上 – 这也避免了ASP.NET SynchronizationContext同时保留在同一个线程上 – 但是一些ASP.NET调用假定存在ASP.NET SynchronizationContext并且将失败.
你可以试试另一个黑客;它可能会奏效,但我从来没有这样做过.只需让你的处理程序返回一个Task< ActionResult>并使用Task.FromResult返回视图:return Task.FromResult< ActionResult>(View(…));这个hack会告诉ASP.NET你的处理程序是异步的(即使它不是).
当然,所有这些黑客都有一个主要的缺点,就是你正在进行同步异步(this.ExtSvc.UpdateRequest(arguments).Result),这意味着你将在每个黑手的持续时间内使用一个额外的不必要的线程.请求(或两个线程,如果您使用Task.Run hack).因此,您将首先忽略使用异步处理程序的所有好处 – 即可伸缩性.
内容总结
以上是互联网集市为您收集整理的c# – ASP中的异步Web服务. NET MVC全部内容,希望文章能够帮你解决c# – ASP中的异步Web服务. NET MVC所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。