我有一个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?
答案 0 :(得分:15)
有可能这样做,但有点尴尬。 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。
答案 1 :(得分:0)
您可能无法使ASMX服务本身以异步方式运行,但是如果您正在使用javascript从WebApp进行调用,则可以在调用时将服务包装在服务中,以便在客户端中利用异步-侧。
如上所述,它不会使您的服务异步,而是在客户端中以异步方式使用此服务的示例(即,在这种情况下使用javascript promise来停止进一步的操作,直到该服务解决为止。同样,可以对其进行调整以在解决或失败后继续操作并执行其他操作。
优化服务本身只是解决方案的一半,另一半是在客户端内部,因此我认为这对某些扩展很有帮助:)
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;
}
答案 2 :(得分:-1)
如果您的问题只是将异步逻辑的顶部集成到asmx中,则可以执行以下代码段。
[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();
}
}