【问题标题】: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?

【问题讨论】:

标签: c# wcf web-services asynchronous 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 阻塞,首先否定异步的任何好处。
    猜你喜欢
    • 2018-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-15
    • 1970-01-01
    相关资源
    最近更新 更多