在并发线程上管理任务的取消和完成

时间:2019-04-02 21:01:51

标签: c# multithreading

[这个问题需要重新构想。我的线程队列之一必须在STA线程上运行,并且下面的代码无法容纳该线程。特别是Task <>似乎选择了自己的线程,而这对我来说是行不通的。 ]

我有一个正在专用线程上运行的任务队列(BlockingCollection)。该队列接收一系列Task <>对象,它通过while循环在该线程内顺序运行。

我需要一种取消一系列任务的方法,并且需要一种知道所有任务都已完成的方法。我无法弄清楚该怎么做。

这是我的排队课程的一部分。 ProcessQueue在与main不同的线程上运行。 QueueJob调用发生在主线程上。

using Job = Tuple<Task<bool>, string>;
public class JobProcessor
{
  private readonly BlockingCollection<Job> m_queue = new BlockingCollection<Job>();
  volatile bool cancel_queue = false;
  private bool ProcessQueue()
  {
     while (true)
     {
        if (m_queue.IsAddingCompleted)
           break;
        Job tuple;
        if (!m_queue.TryTake(out tuple, Timeout.Infinite))
           break;

        var task = tuple.Item1;
        var taskName = tuple.Item2;

        try
        {
           Console.WriteLine("Task {0}::{1} starting", this.name, taskName);
           task.RunSynchronously();
           Console.WriteLine("Task {0}::{1} completed", this.name, taskName);
        }
        catch (Exception e)
        {
           string message = e.Message;
        }
        if (cancel_queue) // CANCEL BY ERASING TASKS AND NOT RUNNING.
        {
           while (m_queue.TryTake(out tuple))
           {
           }
        }
     } // while(true)

     return true;
  }

  public Task<bool> QueueJob(Func<bool> input)
  {
     var task = new Task<bool>(input);
     try
     {
        m_queue.Add(Tuple.Create(task, input.Method.Name));
     }
     catch (InvalidOperationException)
     {
        Task<bool> dummy = new Task<bool>(() => false);
        dummy.Start();
        return dummy;
     }
     return task;
  }

以下是困扰我的功能:

  public void ClearQueue()
  {
     cancel_queue = true;
     // wait for queue to become empty.  HOW?
     cancel_queue = false;
  }
  public void WaitForCompletion()
  {
     // wait for all tasks to be completed.  
     // not sufficient to wait for empty queue because the last task
     // must also execute and finish.  HOW?
  }
}

这里是一些用法:

class SomeClass
{
   void Test()
   {
      JobProcessor jp = new JobProcessor();
      // launch Processor loop on separate thread... code not shown.
      // send a bunch of jobs via QueueJob... code not show.
      // launch dialog... code not shown.
      if (dialog_result == Result.Cancel)
          jp.ClearQueue();
      if (dialog_result == Result.Proceed)
          jp.WaitForCompletion();
   }
}

想法是在工作完成或取消之后,可能会发布新工作。通常,新的工作可能会异步进行。实际上,WaitForCompletion可能是“当所有工作完成后,通知用户然后再做其他事情”,因此,严格来说,它不一定像上面那样是一个同步函数调用,但是我不知道如何实现这些功能。

(更复杂的是,我希望有多个交互的队列。尽管我谨慎地将事物并行化以防止死锁,但是我不确定将取消引入到混合中会发生什么,但这很可能超出此问题的范围。)

1 个答案:

答案 0 :(得分:0)

WaitForCompletion()听起来很容易。创建一个信号灯或事件,创建一个任务,该任务的唯一动作是发出信号灯,将任务排队,等待信号灯。

当线程完成最后一个“真实”任务时,将运行信号量任务,因此名为WaitForCompletion的线程将准备就绪/正在运行:)

类似的取消方法行不通吗?您创建/发出一个具有很高优先级的线程,以耗尽所有待处理作业的队列,处理它们,排队信号量任务并等待“最后一个任务完成”信号?