实现HttpWebRequest异步方法

时间:2013-07-22 18:04:35

标签: c# .net asynchronous iasyncresult

出于各种原因,我一直致力于更改现有的同步IO绑定代码,例如在我们使用的服务中非常频繁地使用HttpWebRequest类发送出站HTTP请求。

我知道async / await以及对.NET 4.5的更改,但我们目前正在使用.NET 4.0。我也知道Microsoft.Bsl.Async,由于其他原因,目前还不是一个选项。

我使用This Article on Async with HttpWebRequest中的示例代码作为参考。

我的问题是,如果我没有更新UI,或者在BeginXXXX和EndXXXX之间做其他事情,但是出站IO调用的时间分别是40+秒,是否值得实现此异步,或者我应该坚持同步执行吗?

1 个答案:

答案 0 :(得分:0)

我会说它绝对值得。这是一个主观判断调用,特别是在服务器端,但40秒是非常重要的。假设您的服务不受CPU限制,我会说大约0.5秒足够快,您可以考虑使其同步。 40秒,绝对是异步。

如果您使用的是.NET 4.0,那么就无法使用Microsoft.Bcl.Async。但是,如果您的服务是其他内容(例如,Win32服务),那么您可以使用Microsoft.Bcl.Async。无论哪种方式,都可以计划升级到.NET 4.5。你将要知道async会给你带来多少痛苦。

关于您的代码结构,我建议采用以下两种方法之一:

  1. 使用Event-based Asynchronous Pattern (EAP)
  2. Asynchronous Programming Model (APM) API周围使用Task包装。
  3. EAP方法更清洁。使用EAP,您可以使用WebClient代替HttpRequest。例如,调用DownloadStringAsync方法并处理DownloadStringCompleted事件。这样做的好处是EAP将通知您当前的上下文正在进行异步操作,在操作完成时再次通知它,并使用该上下文来执行事件处理程序。如果您托管在ASP.NET中,这一点尤其重要。

    EAP模式的缺点是总是使用上下文(即使你不需要它)。

    Task APM包装器方法需要更多工作。使用此方法,您可以使用TaskFactory.FromAsync创建Task - 围绕Begin / End对返回方法。然后使用返回的Task<T>上的成员来安排完成(Task.ContinueWith)。

    Task APM包装器方法的缺点是从不使用上下文,因此如果您在ASP.NET上托管,则需要自己做通知( SynchronizationContext.OperationStartedSynchronizationContext.OperationCompleted)。您也可能(可能)必须捕获上下文(TaskScheduler.FromCurrentSynchronizationContext)并在计划延续时将其传递给ContinueWith,以便它们在该上下文中运行。

    如果您正在创建其余代码使用的实际组件,Task APM包装器方法确实具有另一个优势:更容易转换为Task-based Asynchronous Pattern使用的{{3}} {1}} / async