有啥方法可以处理 ASMX 服务后面的 async/await 吗?
Posted
技术标签:
【中文标题】有啥方法可以处理 ASMX 服务后面的 async/await 吗?【英文标题】:Is there some way to handle async/await behind an ASMX service?有什么方法可以处理 ASMX 服务后面的 async/await 吗? 【发布时间】:2013-09-08 11:08:25 【问题描述】:我有一个 Web 应用程序为 JSON 和一个 ASMX Web 服务提供 WCF REST API。该应用程序已经存在了几年。它基于 ASP.NET 2.0,但几年前升级到 .NET 4.0,而我刚刚升级到 .NET 4.5 以便能够使用新的异步框架。
应用程序的背后是一些遗留服务,我意识到通过异步提高性能的潜力很大。我已经在整个应用程序中实现了异步,并且通过 WCF REST API 一切正常。
我发现 ASMX API 失败为时已晚,我想要这样的方法:
[WebMethod(Description = "Takes an internal trip ID as parameter.")]
async public Task<Trip> GetTrip(int tripid)
var t = await Trip.GetTrip(tripid);
return t;
然后我了解到 ASMX 根本不支持 async/await,每个人都建议迁移到 WCF。我对此不太高兴。 ASMX(实际上是其中三个)塞满了不同的方法,并且我们希望通过旧 API 继续提供大量 API 使用者。
但我们需要提高性能!有人知道一种解决方法,以便我可以继续在 ASMX 后面使用 async/await,但像以前一样公开 ASMX?
【问题讨论】:
你明白异步只有在特殊情况下才会更快吗?可能会慢一些。先研究一下。 Calling Task-based methods from ASMX 的可能重复项 【参考方案1】:也许可以这样做,但会有点尴尬。 ASMX supports APM-style asynchronous methods,您也可以convert TAP to APM(但是请注意,该页面上的 MSDN 示例没有正确传播异常)。
我的博客上有一个示例显示how to wrap TAP implementations in APM(异常传播保持正确的异常类型但丢失堆栈;请参阅ExceptionDispatchInfo
以获得完全正确的异常传播)。当 WCF 仅支持 APM 时,我使用了一段时间。一个非常相似的方法应该适用于 ASMX。
但是,请注意您将have to target 4.5 (i.e., httpRuntime.targetFramework
) for async
/await
to work as expected。
【讨论】:
嗨,Stephen,将 EAP 包装到 Task 中会是假的异步吗?例如正如你所建议的here @HarisMunawar:不。“假异步”正在阻塞线程池线程以提供异步 API。 EAP 是异步的,所以没有线程池线程阻塞。【参考方案2】:您可能无法使 ASMX 服务本身以异步方式运行,但如果您使用 javascript 从 WebApp 调用,则可以在调用时将 promise 包裹在服务周围,以利用客户端中的异步- 侧面。
如上所述,它不会使您的服务异步,而是在客户端内以异步方式使用此服务的示例(即,在此实例中使用 javascript 承诺来停止进一步的操作,直到服务解决。同样,它可以调整为在解决或失败后继续操作并执行其他操作)。
优化服务本身只是解决方案的一半,另一半在客户端内部,所以我认为这对某些人来说是一个有益的扩展:)
Javascript 代码:
var tripObj;
async function getTripObject(tripId)
// Ensures Trip is fetched before proceeding
var promise = new Promise(function (resolve, reject)
ASMXService.getTrip(tripId, async function (ret)
tripObj = ret;
resolve("Success");
, function ()
reject("Error");
);
);
await promise;
【讨论】:
【参考方案3】:如果您的问题只是将异步逻辑的顶部集成到您的 asmx 中,您可以像下面的 sn-p 那样做。
[WebMethod(Description = "Takes an internal trip ID as parameter.")]
public Trip GetTrip(int tripid)
var trip = Trip.GetTrip(tripid).Wait();
return trip;
请注意,如果 Trip.GetTrip() 抛出异常,您将收到 AggregateException,而不是等待抛出异常时收到的异常。你可以这样做
[WebMethod(Description = "Takes an internal trip ID as parameter.")]
public Trip GetTrip(int tripid)
try
var trip = Trip.GetTrip(tripid).Wait();
return trip;
catch(AggregateException ex)
throw ex.InnerException.First();
【讨论】:
使用 .Wait() 将导致 WebMethod 阻塞,首先否定异步的任何好处。以上是关于有啥方法可以处理 ASMX 服务后面的 async/await 吗?的主要内容,如果未能解决你的问题,请参考以下文章
有啥方法可以在不使用 Nest.js 中的 async/await 的情况下从数据库中获取数据?
Promises => Async/Await....这有啥好处吗?