有啥方法可以处理 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 吗?的主要内容,如果未能解决你的问题,请参考以下文章

web service接口 wsdl和asmx有啥区别

有啥方法可以在不使用 Nest.js 中的 async/await 的情况下从数据库中获取数据?

有啥方法可以拥有 ASYNC MessageBox 吗?

Promises => Async/Await....这有啥好处吗?

当我们在webservice.asmx.cs中编写所有代码时,webservice.asmx有啥用?

用 async/await 来处理异步