C#中的同步任务队列

时间:2014-03-07 22:05:32

标签: c# multithreading delegates queue

我有一个多线程环境,需要同步调用特殊任务(一个接一个)。

我创建了一个名为SynchronizedWorker的简单静态类,其中包含Queue个委托和锁。它包含一个ProcessTask方法,该方法将新任务放入队列并等待任务完成。

它还包含ProcessTasks私有方法,用于处理单独线程上的所有任务。如果在新任务到达时它正在运行,那么任务就会被置于队列中,我们会等待。

要通知调用者他的特定任务已完成,将为该任务创建一个ManualResetEvent实例。但是,我不确定这是否是一个“好”的解决方案,因为可能有许多这样的任务排队等待,也许一个锁就足够了:

public static class SynchronizedWorker
{
    private static Queue<KeyValuePair<Action, ManualResetEvent>> tasks = new Queue<KeyValuePair<Action, ManualResetEvent>>();
    private static bool isProcessingTasks = false;
    private static object syncRoot = new object();

    public static void ProcessTask(Action task)
    {
        ManualResetEvent waitHandle = new ManualResetEvent(false);

        bool startProcessing;

        lock (syncRoot)
        {
            tasks.Enqueue(new KeyValuePair<Action, ManualResetEvent>(task, waitHandle));

            // check if task processing need to start over
            startProcessing = (isProcessingTasks == false);

            isProcessingTasks = true;
        }

        if (startProcessing)
        {
            // start task processing
            Task.Factory.StartNew(ProcessTasks);
        }

        // wait until our task is done
        waitHandle.WaitOne();
    }

    private static void ProcessTasks()
    {
        while (true)
        {
            Action task;
            ManualResetEvent waitHandle;

            lock (syncRoot)
            {
                if (tasks.Count == 0)
                {
                    // all done
                    isProcessingTasks = false;

                    break;
                }

                var pair = tasks.Dequeue();

                task = pair.Key;
                waitHandle = pair.Value;
            }

            // perform the task
            task();

            // signal that we are done
            waitHandle.Set();
        }
    }
}

2 个答案:

答案 0 :(得分:0)

AutoResetEvent就足够了:

public static class SynchronizedWorker
{
    private static AutoResetEvent waitHandle = new AutoResetEvent(false);

    public static void ProcessTask(Action task)
    {
        if (waitHandle.WaitOne())
        {
            Task.Factory.StartNew((() =>
            {
                // process task
                task();

                // signal that we are done
                waitHandle.Set();
            }));
        }
    }
}

答案 1 :(得分:0)

我不确定这是否100%正确,因为

  1. 你的等待句柄开始被锁定,没有人使用Set()。应该是真的
  2. 您的WaitOne()仍然在主线程中执行。
  3. NR。 2表示当前线程将被阻止,并且不会在&#34;任务中完成#34;方式。也许这正是你想要的,但是对于开始&#34;一些&#34;任务和继续,但只是希望这些任务开始,如果其他人完成,这还不够。