当前位置: 首页 > 知识库问答 >
问题:

在C中同步重任务和轻任务#

任绪
2023-03-14

我正在尝试实现某种具有不同任务权重的任务队列,允许不同数量的任务根据其权重并发运行。

有两种类型的任务:长任务和短任务。最多可以同时执行N个短任务。

当长任务出现时,如果没有其他长任务正在运行,则应立即启动或等待它完成。

如果有长任务运行,则并发短任务计数限制应减少到M。已经运行的短任务应保持运行至完成;但如果当前限制小于或等于当前运行的短任务数量,则不应启动新的短任务。

看起来,我基本上需要动态更改信号量“容量”的能力。在需要时,只需占用/释放(N-M)“插槽”就可以很容易地减少/增加容量,但如果已经有N个短任务在运行,那么这将导致在(N-M)个短任务完成之前“挂起”队列。

我还可以实现某种“调度程序”,例如每100毫秒唤醒一次,并检查队列中现在可以启动的任务。这种方法的缺点是在将任务排入队列和启动任务之间有高达100毫秒的延迟。

所以我一直在想这个难题,希望有人能对如何实现这个有一些新的想法。

更新:任务不会产生任何显著的CPU负载。它们实际上是HTTP请求。长请求是上载文件,短请求是常见的HTTP请求。

共有1个答案

曹波鸿
2023-03-14

几天前我回答了一个非常相似的问题,对你的解决方案几乎完全相同,使用“ParallelExtensionsExtras”中的QueuedTaskScheduler

private static void Main(string[] args)
{
    int highPriorityMaxConcurrancy = 1

    QueuedTaskScheduler qts = new QueuedTaskScheduler();
    var highPriortiyScheduler = qts.ActivateNewQueue(0);
    var lowPriorityScheduler = qts.ActivateNewQueue(1);

    BlockingCollection<HttpRequestWrapper> fileRequest= new BlockingCollection<Foo>();
    BlockingCollection<HttpRequestWrapper> commonRequest= new BlockingCollection<Foo>();

    List<Task> processors = new List<Task>(2);

    processors.Add(Task.Factory.StartNew(() =>
    {
        Parallel.ForEach(fileRequest.GetConsumingPartitioner(),  //.GetConsumingPartitioner() is also from ParallelExtensionExtras, it gives better performance than .GetConsumingEnumerable() with Parallel.ForEeach(
                         new ParallelOptions() { TaskScheduler = highPriortiyScheduler, MaxDegreeOfParallelism = highPriorityMaxConcurrancy }, 
                         ProcessWork);
    }, TaskCreationOptions.LongRunning));

    processors.Add(Task.Factory.StartNew(() =>
    {
        Parallel.ForEach(commonRequest.GetConsumingPartitioner(), 
                         new ParallelOptions() { TaskScheduler = lowPriorityScheduler}, 
                         ProcessWork);
    }, TaskCreationOptions.LongRunning));


    //Add some work to do here to the fileRequest or commonRequest collections


    //Lets the blocking collections know we are no-longer going to be adding new items so it will break out of the `ForEach` once it has finished the pending work.
    fileRequest.CompleteAdding();
    commonRequest.CompleteAdding();

    //Waits for the two collections to compleatly empty before continueing
    Task.WaitAll(processors.ToArray());
}

private static void ProcessWork(HttpRequestWrapper request)
{
    //...
}
 类似资料:
  • 1.需求背景 在积分商城,或者签到页面中,开发者涉及到做任务领取奖励的情况,比如听歌,看书,开通会员等页面操作任务之后,在签到页面可以领取积分奖品等特殊奖品。因此需要涉及到签到任务同步接口。 接口有开发者提供,由兑吧触发请求。 2.接口请求说明(Get请求) 请求参数 字段名 字段类型 是否必须 字段数码 appKey string yes 接口appKey,应用的唯一标识 uid String

  • 问题内容: 我正在Flask中编写一个应用程序,除了同步和阻塞之外,它的运行情况非常好。我特别有一项任务,该任务调出第三方API,该任务可能需要几分钟才能完成。我想拨打该电话(实际上是一系列电话)并使其运行。同时控制权返回给Flask。 我的看法如下: 现在,我要做的就是 运行并提供在方法返回时要执行的回调,而Flask可以继续处理请求。这是我需要Flask异步运行的唯一任务,并且我想就如何最好地

  • 本文向大家介绍C#异步执行任务的方法,包括了C#异步执行任务的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#异步执行任务的方法。分享给大家供大家参考。具体如下: 希望本文所述对大家的C#程序设计有所帮助。

  • 同步任务 ( Sync ) 任务继承自复制任务 ( Copy ) , 当它执行时,它会复制源文件到目标目录中,然后从目标目录中的删除所有非复制的文件,这种方式非常有用,比如安装一个应用,创建一个文档的副本,或者维护项目的依赖关系副本. 下面有一个例子,维护 build/libs 目录下项目在运行时的依赖 例 15.7 使用 Sync 任务复制依赖关系 build.gradle task libs(

  • 我是JavaFx/并发的新手,所以我在JavaFX中阅读了并发教程,但是我仍然对JavaFX Gui中后台线程的实现有点困惑。 我试图编写一个与一些串行设备(使用JSSC-2.8)接口的小图形用户界面,并根据这些设备的响应更新图形用户界面。但是,在写入消息和设备响应之间有一个延迟,在任意的时间内使用Thread.sleep()对我来说不是一个可靠的编程方式。因此,我想使用并发包中的等待()和通知(

  • 主要内容:本节引言:,1.相关概念,2.AsyncTask全解析:,3.AsyncTask使用示例:,本节小结:本节引言: 本节给大家带来的是Android给我们提供的一个轻量级的用于处理异步任务的类:AsyncTask,我们一般是 继承AsyncTask,然后在类中实现异步操作,然后将异步执行的进度,反馈给UI主线程~ 好吧,可能有些概念大家不懂,觉得还是有必要讲解下多线程的概念,那就先解释下一些概念性的东西吧! 1.相关概念 1)什么是多线程: 答:先要了解这几个名称:应用程序,进程,线程,