提供异步编程模型:我应该吗?如果是这样,它应该是VerbAsync()还是BeginVerb()?

Che*_*eso 5 .net asynchronous class-design

在c#中提供Method的同步和异步版本会询问如何提供方法的异步版本.

其中一个答案表明,类库开发人员应尽可能避免在单一责任原则的基础上提供异步方法.

  1. 这是真的?
    我不应该提供异步版本的方法吗?

  2. 如果答案为(换句话说,DO提供方法的异步版本),那么我应该遵循这篇MSDN文章中的建议,该文章指出:

IAsyncResult设计模式允许各种编程模型,但学习起来更复杂,并提供大多数应用程序不需要的灵活性.在可能的情况下,类库设计者应该使用事件驱动模型实现异步方法.在某些情况下,库设计者还应该实现基于IAsyncResult的模型.

??

"事件驱动模型"是指如果方法的同步版本是Verb(),则该方法的异步版本是Verb Async(),并且存在Verb Completed事件.
IAsyncResult模式是众所周知的Begin Verb()和End Verb()方法.

Phi*_*hil 6

您为什么要考虑提供异步API?

API操作是IO绑定还是CPU绑定?(这是因为等待IO完成需要很长时间,还是只是CPU密集型?)

如果CPU绑定,我会考虑是否真的有必要提供异步版本,因为调用者总是可以通过线程池有效地将同步操作转换为异步操作.

提供异步API的最重要原因是针对IO绑定的操作.不是捆绑线程以等待高延迟IO操作,而是优选使用异步IO.这尤其会影响系统的可扩展性.例如,如果您在单个同步IO操作上阻塞了服务器,那么问题就不是太多了 - 您只是占用了一个线程.但是,同时执行1000个相同的操作,并且你要占用1000个线程(如果内存为每个线程提供1MB的堆栈),只需等待几个CPU周期的操作完成.最终结果 - 你有一个空闲的CPU,但正在吸收资源.

因此,例如,如果您自己编写套接字库,那么您肯定希望提供异步IO操作,以便库的用户可以编写可伸缩的应用程序.

例如,如果您正在编写加密库,那么即使操作可能需要很长时间,也可能没有迫切需要提供异步API - 无论如何它都是CPU绑定的.如上所述,用户可以使其异步.

最后,如果您正在编写一个IO绑定系统,该系统使用提供异步IO的低级API(例如,使用套接字类的FTP客户端),您可能还需要考虑提供API的异步版本.但事情是这样做并不容易 - 如果您使用较低级别的API的异步功能,则只能提供可伸缩性优势.这很快就会导致简单的同步逻辑转变为极其复杂,难以调试的异步逻辑.主要问题是您之前通过局部变量进行了简单访问的所有状态信息最终需要手动捕获,以便在下一个IO操作完成时,您的逻辑知道下一步该做什么.

提供一个异步API然后在内部调用同步IO操作是没有意义的(尽管我已经看到它完成了).给出了可伸缩性的错觉,但......不是!

当.NET 4.0问世时,其中一些可能会变得更简单(虽然我认为从我看到它仍然会很棘手).

与此同时,您可能需要查看Jeffrey Richter的异步枚举器库,它可以帮助简化(稍微):

杰弗里里希特对他的异步调查员

电源线程库包括异步枚举器

菲尔,希望这会有所帮助.

注意:如果您要实现异步API,我建议通过"经典开始/结束"IAsyncResult API提供它.原因是,从我记忆中,它应该与.NET 4.0的任务并行库更好地集成.