【问题标题】:Asynchronous methods and asynchronous delegates异步方法和异步委托
【发布时间】:2010-11-27 22:50:07
【问题描述】:

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

这本书是这么说的。

异步方法

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

异步委托

  1. 可能会阻塞任意时间
  2. BeginInvoke 立即返回给调用者。
  3. 内置编译器支持。

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

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

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

有什么想法吗?

【问题讨论】:

  • codezone4 有很好的教程。点击here

标签: c# .net multithreading asynchronous


【解决方案1】:

当您使用回调调用 BeginFoo() 时,您可能会看到两种主要行为。

  1. 工作在后台线程上启动,该线程将一直使用,直到工作完成并调用回调(例如,因为工作是同步的)。
  2. 尽管后台线程上发生了一些工作,但线程不必一直处于使用状态(例如,因为工作涉及可以在 IOCompletionPort 上安排回调的系统 IO)。

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

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

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

正如你所说,#2 的优点是你可以拥有例如100 次挂起的 IO 调用而不消耗 100 个线程(线程很昂贵)。

【讨论】:

    【解决方案2】:
    1. 实现可以不同;例如,异步 IO 调用可能会选择使用完成端口,以最大限度地降低系统成本,同时不执行任何操作。
    2. 肯定是一种方式;您还可以在 .NET 4.0 中使用 BackgroundWorkerThreadPool.QueueUserWorkItemParallel.For(等)
    3. 因实施而异

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

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

    但这不是唯一的模式。还;最近(例如,Silverlight 或 WebClient 中的异步 IO 方法):使用事件来表示完成,而不是 IAsyncResult

    【讨论】:

    • 感谢您的回复。你能指出一个具有不同异步方法实现的框架类吗?
    • 可能类似于 SqlCommand.BeginExecute*HttpWebRequest.BeginGetResponse
    猜你喜欢
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    • 1970-01-01
    • 2022-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多