有一组仅一次运行X的任务

假设我有100项任务需要10秒钟来完成。现在,我只想一次运行10个,例如这10个中的1个完成另一个任务,直到全部完成。

现在,我总是使用ThreadPool.QueueUserWorkItem()这种任务,但是我已经读到这样做是不好的做法,应该改用Tasks。

我的问题是,我在任何地方都找不到适合自己的案例的好例子,因此您可以让我开始如何通过Tasks实现此目标吗?


一只名叫tom的猫
浏览 443回答 3
3回答

慕田峪9158850

SemaphoreSlim maxThread = new SemaphoreSlim(10);for (int i = 0; i < 115; i++){&nbsp; &nbsp; maxThread.Wait();&nbsp; &nbsp; Task.Factory.StartNew(() =>&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Your Works&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; , TaskCreationOptions.LongRunning)&nbsp; &nbsp; .ContinueWith( (task) => maxThread.Release() );}

慕的地8271018

TPL Dataflow非常适合执行此类操作。您可以轻松创建100%异步版本Parallel.Invoke:async Task ProcessTenAtOnce<T>(IEnumerable<T> items, Func<T, Task> func){&nbsp; &nbsp; ExecutionDataflowBlockOptions edfbo = new ExecutionDataflowBlockOptions&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MaxDegreeOfParallelism = 10&nbsp; &nbsp; };&nbsp; &nbsp; ActionBlock<T> ab = new ActionBlock<T>(func, edfbo);&nbsp; &nbsp; foreach (T item in items)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;await ab.SendAsync(item);&nbsp; &nbsp; }&nbsp; &nbsp; ab.Complete();&nbsp; &nbsp; await ab.Completion;}

呼啦一阵风

您有几种选择。您可以使用Parallel.Invoke入门:public void DoWork(IEnumerable<Action> actions){&nbsp; &nbsp; Parallel.Invoke(new ParallelOptions() { MaxDegreeOfParallelism = 10 }&nbsp; &nbsp; &nbsp; &nbsp; , actions.ToArray());}这是一个替代选项,它将很难工作以恰好运行10个任务(尽管处理这些任务的线程池中的线程数可能不同),并Task在完成时返回指示,而不是直到完成才阻塞。public Task DoWork(IList<Action> actions){&nbsp; &nbsp; List<Task> tasks = new List<Task>();&nbsp; &nbsp; int numWorkers = 10;&nbsp; &nbsp; int batchSize = (int)Math.Ceiling(actions.Count / (double)numWorkers);&nbsp; &nbsp; foreach (var batch in actions.Batch(actions.Count / 10))&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; tasks.Add(Task.Factory.StartNew(() =>&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; foreach (var action in batch)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }));&nbsp; &nbsp; }&nbsp; &nbsp; return Task.WhenAll(tasks);}如果您没有MoreLinq,则此Batch功能是我更简单的实现:public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int batchSize){&nbsp; &nbsp; List<T> buffer = new List<T>(batchSize);&nbsp; &nbsp; foreach (T item in source)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; buffer.Add(item);&nbsp; &nbsp; &nbsp; &nbsp; if (buffer.Count >= batchSize)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yield return buffer;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buffer = new List<T>();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; if (buffer.Count >= 0)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; yield return buffer;&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP