23

我有一个 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?

4

3 回答 3

22

这样做可能是可行的,但会有点尴尬。ASMX 支持 APM 样式的异步方法,您可以将 TAP 转换为 APM(但是,请注意该页面上的 MSDN 示例不会正确传播异常)。

我的博客上有一个示例,展示了如何在 APM 中包装 TAP 实现(异常传播保持正确的异常类型但丢失了堆栈;请参阅ExceptionDispatchInfo完全正确的异常传播)。当 WCF 只支持 APM 时,我使用了一段时间。一个非常相似的方法应该适用于 ASMX。

但是,请注意,您必须将目标设置为 4.5(即httpRuntime.targetFramework),async才能await按预期工作

于 2013-09-04T21:01:54.203 回答
0

您可能无法使 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;

}
于 2019-08-15T12:31:40.970 回答
-2

如果您的问题只是将异步逻辑的顶部集成到您的 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();
  }       
}
于 2014-07-09T17:25:42.380 回答