代码之家  ›  专栏  ›  技术社区  ›  Ian Mercer

用任务并行库实现“only one of”和“not in parallel”语义

  •  1
  • Ian Mercer  · 技术社区  · 15 年前

    选项1)此密钥中只有一个处于挂起状态。例如,可以从ASP.NETMVC将一个缩略图图像的单个呈现排队,而不管该图像Url被点击多少次。只有一个请求运行,所有其他请求等待该请求完成。

    选项2)具有相同键的所有项必须按顺序执行。例如,可用于确保将文件从备份存储提取到本地缓存的操作不会同时尝试将文件提取到缓存。选项1是这种情况的一个特例,其中使用相同键的后续操作被简单地丢弃(通常只保存一个文件存在检查)。

    我有一个处理这两种情况的现有工作队列(以及单元状态、线程优先级设置和最大并行度)。第三方物流似乎是取代这一点的最佳解决方案,并将带来更好的取消选择。

    具有连续性的嵌套任务看起来很有希望,但是维护一个包含当前队列任务的字典很快就会在TaskFactory和TaskScheduler类之间变得混乱。从任务继承也是有问题的,因为TaskFactory和TaskScheduler在任务上都不是泛型的。

    2 回复  |  直到 15 年前
        1
  •  1
  •   VinayC    15 年前

    也许,我能想到的一个方法是

    1. 创建一个包装类-比如说KeyProcessor来为一个键排队。
    2. 对于任何新任务,请在字典中查找相同的键。如果不存在,则添加它。对其上的任务进行排队。如果它没有运行,那么使用Run方法作为操作用TPL来调度它。
    3. 使用ContinueWith计划维护者任务-例如,每当任务执行时键盘处理器。运行如果已完成,则继续任务可以检查是否为同一个键安排了其他任务(因为它已完成),然后重新启动它或从字典中删除。

    System.Collections.Concurrent 命名空间。这将使上述逻辑更加简单。例如, ConcurrentDictionary.GetOrAdd 将允许以线程安全的方式查找和/或添加KeyProcessor对象。

        2
  •  1
  •   Ana Betts    15 年前

    这个问题和我在中解决的问题很相似 ReactiveXaml ,不过我也记下了以前的请求。看一下代码 QueuedAsyncMRUCache blog entry )-此代码将TPL与反应式扩展结合起来,以完成此类操作,但它提供了一个重要的保证,即对同一密钥的第二个请求将在第一个飞行中请求时被阻止,而不是发出另一个请求。