为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C++
一只名叫tom的猫 2019-11-03 08:04:02
假设我有100项任务需要10秒钟来完成。现在,我只想一次运行10个,例如这10个中的1个完成另一个任务,直到全部完成。现在,我总是使用ThreadPool.QueueUserWorkItem()这种任务,但是我已经读到这样做是不好的做法,应该改用Tasks。我的问题是,我在任何地方都找不到适合自己的案例的好例子,因此您可以让我开始如何通过Tasks实现此目标吗?
查看完整描述

3 回答

?
慕田峪9158850

TA贡献1794条经验 获得超7个赞

SemaphoreSlim maxThread = new SemaphoreSlim(10);


for (int i = 0; i < 115; i++)

{

    maxThread.Wait();

    Task.Factory.StartNew(() =>

        {

            //Your Works

        }

        , TaskCreationOptions.LongRunning)

    .ContinueWith( (task) => maxThread.Release() );

}



查看完整回答
反对 回复 2019-11-04
?
慕的地8271018

TA贡献1796条经验 获得超4个赞

TPL Dataflow非常适合执行此类操作。您可以轻松创建100%异步版本Parallel.Invoke:


async Task ProcessTenAtOnce<T>(IEnumerable<T> items, Func<T, Task> func)

{

    ExecutionDataflowBlockOptions edfbo = new ExecutionDataflowBlockOptions

    {

         MaxDegreeOfParallelism = 10

    };


    ActionBlock<T> ab = new ActionBlock<T>(func, edfbo);


    foreach (T item in items)

    {

         await ab.SendAsync(item);

    }


    ab.Complete();

    await ab.Completion;

}



查看完整回答
反对 回复 2019-11-04
?
呼啦一阵风

TA贡献1802条经验 获得超6个赞

您有几种选择。您可以使用Parallel.Invoke入门:


public void DoWork(IEnumerable<Action> actions)

{

    Parallel.Invoke(new ParallelOptions() { MaxDegreeOfParallelism = 10 }

        , actions.ToArray());

}

这是一个替代选项,它将很难工作以恰好运行10个任务(尽管处理这些任务的线程池中的线程数可能不同),并Task在完成时返回指示,而不是直到完成才阻塞。


public Task DoWork(IList<Action> actions)

{

    List<Task> tasks = new List<Task>();

    int numWorkers = 10;

    int batchSize = (int)Math.Ceiling(actions.Count / (double)numWorkers);

    foreach (var batch in actions.Batch(actions.Count / 10))

    {

        tasks.Add(Task.Factory.StartNew(() =>

        {

            foreach (var action in batch)

            {

                action();

            }

        }));

    }


    return Task.WhenAll(tasks);

}

如果您没有MoreLinq,则此Batch功能是我更简单的实现:


public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int batchSize)

{

    List<T> buffer = new List<T>(batchSize);


    foreach (T item in source)

    {

        buffer.Add(item);


        if (buffer.Count >= batchSize)

        {

            yield return buffer;

            buffer = new List<T>();

        }

    }

    if (buffer.Count >= 0)

    {

        yield return buffer;

    }

}



查看完整回答
反对 回复 2019-11-04
  • 3 回答
  • 0 关注
  • 442 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信