异步方法和异步委托

Nav*_*K N 10 .net c# multithreading asynchronous

简而言之,C#3.0异步方法异步委托看起来很相似,但行为却截然不同.

这是本书所说的两者.

异步方法

  1. 很少或从不阻止任何线程.
  2. Begin方法可能不会立即返回给调用者.
  3. 一个没有C#语言支持的商定协议.

异步代理

  1. 可以阻止任何时间长度
  2. BeginInvoke立即返回给调用者.
  3. 内置编译器支持.

该书还说,异步方法的目的是允许许多任务在少数线程上运行; 异步委托的目的是与调用者并行执行任务.

当我通过反射器查看System.IO.Stream类中的BeginRead()方法时,它正在使用委托并在其上调用BeginInvoke.因此异步方法在内部使用异步委托.

  1. 在这种情况下,怎么能说他们的行为不同?既然它在内部使用委托,那么如何进行上述比较呢?
  2. 您是否认为使用委托的BeginXXX方法是与调用者并行执行函数的方法?
  3. 通过保持充分利用CPU等所有优点来实现异步方法的正确方法是什么?

有什么想法吗?

Bri*_*ian 7

在核心,当您使用回调调用BeginFoo()时,您可能会看到两个主要行为.

  1. 工作在后台线程上启动,该线程将一直使用,直到工作完成并调用回调(例如因为工作是同步的).
  2. 虽然某些工作在后台线程上发生,但线程不需要在整个时间内使用(例如,因为工作涉及可以在例如IOCompletionPort上调度回调的系统IO).

当您使用委托时,会发生上述行为#1.

某些API(具有对非阻塞IO调用的底层支持)支持行为#2.

在'Stream'的特定情况下,我不确定,但我的猜测是它是一个抽象基类,所以这只是一个只实现Read同步版本的子类的默认行为.'good'子类将覆盖BeginRead/EndRead以具有非阻塞实现.

正如你所说,#2的优势在于你可以拥有100个待处理的IO调用而不需要消耗100个线程(线程很昂贵).


Mar*_*ell 5

  1. 实施可能不同; 例如,异步IO调用可以选择使用完成端口来最小化系统成本而不执行任何操作.
  2. 这当然是一种方式; 你也可以在.NET 4.0中使用BackgroundWorker,ThreadPool.QueueUserWorkItemParallel.For(等)
  3. 每个实施都有所不同

我想这本书试图强调的是代表们总是包含这种模式:

  • Invoke可以阻止的同步调用()
  • BeginInvoke除非线程池已饱和,否则不应该真正阻塞的异步调用()

但它不是唯一的模式.也; 最近(例如,Silverlight中的异步IO方法,或者WebClient):而不是a IAsyncResult,事件用于表示完成.

  • 也许类似于`SqlCommand.BeginExecute*`或`HttpWebRequest.BeginGetResponse` (2认同)