【问题标题】:Controlling the number of threads when using c#5 async / await使用 c#5 async / await 时控制线程数
【发布时间】:2011-12-22 20:14:51
【问题描述】:

我正在研究在 c#5 中使用新的 async/await 密钥并阅读 this article

我看到下面的例子

async void ArchiveDocuments(List<Url> urls)
{
  Task archive = null;
  for(int i = 0; i < urls.Count; ++i)
  {
    var document = await FetchAsync(urls[i]);
    if (archive != null)
      await archive;
    archive = ArchiveAsync(document);
  }
}

如果 Urls 列表很长,我们可能会遇到线程数失控的情况。

我想知道控制使用的线程数的推荐方法是什么。有没有办法指定线程池或最大数量?

使用 TPL,您可以使用选项来控制最大线程数 ParallelOptions.MaxDegreeOfParallelism。也许某种结合 await 和 Task 的方式是可能的。

【问题讨论】:

    标签: multithreading async-await c#-5.0


    【解决方案1】:

    该示例的重点是展示一种“管道”模式,其中最多同时执行一个 Fetch 和一个 Archive。

    async 不代表并发,代表非阻塞。

    【讨论】:

    • 感谢您的回复,但我只是将该片段用作在循环中使用 await 的示例。我试图弄清楚它将使用多少个线程。如果 await 处于这样的循环中,那么循环仅在 await 返回后继续。来自那篇文章:“如果我们正在等待的任务尚未完成,则注册此方法的其余部分作为该任务的延续,然后立即返回给您的调用者;任务完成后将调用延续。”这似乎表明只有一个线程将用于 FetchAsync
    • 当您执行await 表达式时,async 方法的其余部分,包括循环索引等任何状态,都存储在状态机对象中。然后async 方法将控制权返回给它的调用者——它退出了。所以不,循环不会继续执行。当等待的方法完成时,控制权返回状态机,然后继续执行。
    • 这里有一些并发,如果你换个角度看的话。当async 方法由于await 返回其调用者时,async 方法本身不会继续运行,但Fetch 和/或Archive 操作执行。我认为async/await 是一种以程序员友好的方式管理并发的方式。
    • @chrisp_68: Tasks 不一定使用线程。 Fetch 可能是 I/O 绑定的,所以它根本不会使用线程。如果Archive 也是I/O 绑定的,并且如果ArchiveDocuments 是从UI 线程调用的,那么根本不会使用线程池(除了非常短的操作,例如完成异步I/O)。 TaskCompletionSource 是用于创建无线程Tasks 的类。
    【解决方案2】:

    asyncawait 关键字本身不会创建任何线程。这完全取决于处理任务本身的方法。

    事实上,像文件系统 I/O 或网络连接这样的操作,通常不需要任何线程来异步运行。硬件执行硬件的操作,完成后触发相关事件(返回 C#)。

    如果你想控制线程的数量,你需要改变创建线程的方法——这与asyncawaits无关。

    【讨论】:

      猜你喜欢
      • 2013-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-12
      • 1970-01-01
      相关资源
      最近更新 更多