【问题标题】:long running process interlock长时间运行的进程互锁
【发布时间】:2011-10-31 11:39:10
【问题描述】:

我正在创建一个 webservice+servicebus 项目,用户可以在其中执行类似的操作

public void ExecuteLongProcess(DateTime fromDate,string aggregateId){}

此方法立即返回,但通过总线发送操作请求。

我的问题开始于多个用户在另一个已经运行的情况下通过同一个 aggregateId 请求长进程。

我正在考虑的解决方案是一个连续运行的任务,并在Queue<LongProcessTask> 中查找必须执行的操作,因此我一次只运行一个进程,否则如果聚合 ID 不同,未来的实现将是多个进程。

这样我就不会在同一个聚合上重叠长时间运行的进程。

其他想法?

【问题讨论】:

  • 当然,非常标准的生产者/消费者场景。线程安全队列和单个线程完成工作。

标签: c# servicebus long-running-processes


【解决方案1】:

我创建了一个 TaskRunner,它实例化一些连续运行的任务(数量取决于处理器内核),这些任务在并发队列中查找并运行每个挂起的操作。 TaskRunner 从 Windsor 获取每个操作类型的处理程序,以便将每个操作的处理放在一个类中。

【讨论】:

    【解决方案2】:

    在您的回答中,您说多个线程将从并发队列中获取任务。在这种情况下,具有相同 aggregateId 的两个任务可能会同时运行。我不知道这对你来说是不是一个问题,如果是这样,那么你必须为每个 aggregateId 使用不同的队列。

    如果任务顺序不是问题,那么我建议使用BlockingCollection。因为有一个问题:如果并发队列中没有任务,您打算如何处理多个消费者线程。

    while(some_condition_to_keep_thread_alive)
    {
      if(!queue.TryDequeue(...))
        continue;
      else 
      {
        //do the job
      }
    }
    

    如果queue 为空,这段代码会让你的内核发疯。你需要一个阻塞机制。 BlockingCollection 将为您完成此操作。

    你坚持使用 ConcurrentQueue 吗?好的SemaphoreSlim是你的朋友。

    【讨论】:

    • 是的,我的队列是 ConcurrentDictionary;在每个线程中,我只得到一个未在其他地方运行并且还按 queuedIn 时间戳排序的 aggregateId 操作。我唯一想念的是信号量。我认为我可以在新操作排队时向线程发出信号
    • 请注意 ConcurrentDictionary 是无序的。如果订单很重要,您可以使用ConcurrentQueue<KeyValuePair<OperationTask,OperationRequest>>。当然,不知道你的实现细节是很难说的。
    • 是的,我知道这一点。我有一个属性 QueuedIn 以便按队列插入时间排序
    猜你喜欢
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多