异步方法和异步委托
简而言之,C#3.0说异步方法和异步委托看起来很相似,但行为却截然不同。
这是本书所说的两者。
异步方法
- 很少或从不阻止任何线程。
- Begin方法可能不会立即返回给调用者。
- 一个没有C#语言支持的商定协议。
异步代理
- 可以阻止任何时间长度
- BeginInvoke立即返回给调用者。
- 内置编译器支持。
该书还说, 异步方法的目的是允许许多任务在少数线程上运行; 异步委托的目的是与调用者并行执行任务 。
当我通过reflection器查看System.IO.Stream类中的BeginRead()方法时,它正在使用委托并在其上调用BeginInvoke 。 因此异步方法在内部使用异步委托。
- 在这种情况下,怎么能说他们的行为不同? 既然它在内部使用委托,那么如何进行上述比较呢?
- 您是否认为使用委托的BeginXXX方法是与调用者并行执行函数的方法?
- 通过保持充分利用CPU等所有优点来实现异步方法的正确方法是什么?
有什么想法吗?
在核心,当您使用回调调用BeginFoo()时,您可能会看到两个主要行为。
- 工作在后台线程上启动,该线程将一直使用,直到工作完成并调用回调(例如因为工作是同步的)。
- 虽然某些工作在后台线程上发生,但线程不需要在整个时间内使用(例如,因为工作涉及可以在例如IOCompletionPort上调度回调的系统IO)。
当您使用委托时,会发生上述行为#1。
某些API(具有对非阻塞IO调用的底层支持)支持行为#2。
在’Stream’的特定情况下,我不确定,但我的猜测是它是一个抽象基类,所以这只是一个只实现Read同步版本的子类的默认行为。 ‘good’子类将覆盖BeginRead / EndRead以具有非阻塞实现。
正如你所说,#2的优势在于你可以拥有100个待处理的IO调用而不需要消耗100个线程(线程很昂贵)。
- 实施可能会有所不同; 例如,异步IO调用可以选择使用完成端口来最小化系统成本而不执行任何操作。
- 这当然是一种方式; 你也可以在.NET 4.0中使用
BackgroundWorker
,ThreadPool.QueueUserWorkItem
或Parallel.For
(etc) - 每个实施都有所不同
我想这本书试图强调的是代表们总是包含这种模式:
- 可以阻止的同步调用(
Invoke
) - 除非线程池已饱和,否则不应该真正阻塞的异步调用(
BeginInvoke
)
但它不是唯一的模式。 也; 最近(例如,Silverlight或WebClient
的异步IO方法):而不是IAsyncResult
,事件用于表示完成。