出于各种原因,我一直致力于更改现有的同步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+秒,是否值得实现此异步,或者我应该坚持同步执行吗?
答案 0 :(得分:0)
我会说它绝对值得。这是一个主观判断调用,特别是在服务器端,但40秒是非常重要的。假设您的服务不受CPU限制,我会说大约0.5秒足够快,您可以考虑使其同步。 40秒,绝对是异步。
如果您使用的是.NET 4.0,那么就无法使用Microsoft.Bcl.Async
。但是,如果您的服务是其他内容(例如,Win32服务),那么您可以使用Microsoft.Bcl.Async
。无论哪种方式,都可以计划升级到.NET 4.5。你将要知道async
会给你带来多少痛苦。
关于您的代码结构,我建议采用以下两种方法之一:
Task
包装。 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.OperationStarted
,SynchronizationContext.OperationCompleted
)。您也可能(可能)必须捕获上下文(TaskScheduler.FromCurrentSynchronizationContext
)并在计划延续时将其传递给ContinueWith
,以便它们在该上下文中运行。
如果您正在创建其余代码使用的实际组件,Task
APM包装器方法确实具有另一个优势:更容易转换为Task-based Asynchronous Pattern使用的{{3}} {1}} / async
。