如何限制多个异步任务? [英] How to throttle multiple asynchronous tasks?

查看:58
本文介绍了如何限制多个异步任务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些以下形式的代码:

I have some code of the following form:

static async Task DoSomething(int n) 
{
  ...
}

static void RunThreads(int totalThreads, int throttle) 
{
  var tasks = new List<Task>();
  for (var n = 0; n < totalThreads; n++)
  {
    var task = DoSomething(n);
    tasks.Add(task);
  }
  Task.WhenAll(tasks).Wait(); // all threads must complete
}

问题是,如果我不限制线程,事情就会开始崩溃.现在,我要启动最多throttle个线程,并且仅在旧线程完成后才启动新线程.我已经尝试了几种方法,但到目前为止都没有奏效.我遇到的问题包括:

Trouble is, if I don't throttle the threads, things start falling apart. Now, I want to launch a maximum of throttle threads, and only start the new thread when an old one is complete. I've tried a few approaches and none so far has worked. Problems I have encountered include:

  • tasks集合必须完全填充所有任务,无论是活动任务还是正在等待执行的任务,否则最后的.Wait()调用仅查看其开始的线程.
  • 束缚执行似乎需要使用Task.Run()等.但是我从一开始就需要参考每个任务,实例化一个任务似乎会自动将其启动,这是我不想要的.
  • The tasks collection must be fully populated with all tasks, whether active or awaiting execution, otherwise the final .Wait() call only looks at the threads that it started with.
  • Chaining the execution seems to require use of Task.Run() or the like. But I need a reference to each task from the outset, and instantiating a task seems to kick it off automatically, which is what I don't want.

该怎么做?

推荐答案

首先,从线程中抽象出来.特别是由于您的操作是异步的,因此您根本不需要考虑线程".在异步世界中,您拥有任务,与线程相比,您可以拥有巨大个任务.

First, abstract away from threads. Especially since your operation is asynchronous, you shouldn't be thinking about "threads" at all. In the asynchronous world, you have tasks, and you can have a huge number of tasks compared to threads.

可以使用SemaphoreSlim来限制异步代码:

Throttling asynchronous code can be done using SemaphoreSlim:

static async Task DoSomething(int n);

static void RunConcurrently(int total, int throttle) 
{
  var mutex = new SemaphoreSlim(throttle);
  var tasks = Enumerable.Range(0, total).Select(async item =>
  {
    await mutex.WaitAsync();
    try { await DoSomething(item); }
    finally { mutex.Release(); }
  });
  Task.WhenAll(tasks).Wait();
}

这篇关于如何限制多个异步任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆