【问题标题】:How to async add elements to Queue<T> in C#?如何在 C# 中将元素异步添加到 Queue<T>?
【发布时间】:2010-10-27 08:02:25
【问题描述】:
public void EnqueueTask(int[] task)
{
    lock (_locker)
    {
        _taskQ.Enqueue(task);
        Monitor.PulseAll(_locker);
    }
}

所以,在这里我将元素添加到我的队列中,然后线程对它们进行一些工作。如何将项目异步添加到我的队列中?

【问题讨论】:

  • 您使用的是什么版本的 .net?
  • 我决定使用 ConcurrentQueue(新的 .NET 4 集合)

标签: c# multithreading asynchronous queue


【解决方案1】:

如果您使用 .net V4,请查看新的线程安全集合,它们大多是非阻塞的,因此可以适当地避免异步添加的需要。

【讨论】:

  • 顺便说一句,谢谢:)。我有来自 .NET 4 的新线程安全集合的书签,你帮助我记住了它们)
【解决方案2】:

由于您使用的是Queue(推荐),因此无法使用Queue.Synchronized。

但除此之外,我会使用线程池。但是您的 EnqueueTask 方法有点暗示线程逻辑是在“TaskQueue”类之外处理的(您的方法暗示它是一个任务队列)。

您的实现还意味着它不是“这里”我们不想添加逻辑,而是在另一个地方,您那里的代码并没有真正阻塞很长时间,所以我会把事情颠倒过来。

这也意味着从队列中取出的东西已经在另一个线程上,因为你使用“PulseAll”来削弱那个线程。

例如

public void StartQueueHandler()
{ 
  new Thread(()=>StartWorker).Start();
}

private int[] Dequeue()
{
  lock(_locker)
  {
    while(_taskQ.Count == 0) Monitor.Wait(_locker);
    return _taskQ.Dequeue();
  }
}

private void StartWorker(object obj)
{
  while(_keepProcessing)
  { 
    //Handle thread abort or have another "shot down" mechanism.
    int[] work = Dequeue();

    //If work should be done in parallel without results.
    ThreadPool.QueueUserWorkItem(obj => DoWork(work));

    //If work should be done sequential according to the queue.
    DoWork(work);
  }
}

【讨论】:

  • 你说得对,我正在处理许多线程中的队列任务,并希望添加异步添加元素的功能。感谢您的回复,但我决定使用“ConcurrentQueue”,恕我直言,我是最简单的方法 :)
  • 问题是您为什么不想添加该功能?将会发生的是,您启动一​​个线程来添加一个元素,并且该线程在几毫秒内再次死亡,因为“添加”一个元素(如果操作正确)不会阻止您。必须启动一个新线程并启动它可能比同步执行它需要更长的时间。显然,在外面的某个地方,你有一个或多个“线程”,它们会反过来添加一些东西,例如通过用户单击按钮或端口上传入的数据等。但您很可能会在那里处理。将您的“入队”方法扩展为异步不会使您受益。
  • 这不是我的决定,任务就是这样)
  • 我使用异步委托将项目异步添加到队列中,而不是特殊的添加管理器负责加载 PC 上的每个核心
【解决方案3】:

也许这样的事情可以工作:

void AddToQueue(Queue queue, string mess) {
    var t = new Thread(() => Queue.Synchronized(queue).Enqueue(mess));
    t.Start();
}

新线程确保您当前的线程不会阻塞。

Queue.Syncronized 处理队列的所有锁定。 它可以用你的储物柜代码代替,可能会更好。

【讨论】:

    【解决方案4】:

    您问题中的代码似乎表明您正在尝试实现阻塞队列。在Queue&lt;T&gt;.Enqueue 之后,我通过调用Monitor.PulseAll 进行了观察。这是发出出队线程信号的正常模式。因此,如果是这种情况,那么最好的选择是使用 .NET 4.0 中可用的 BlockingCollection 类。

    【讨论】:

      猜你喜欢
      • 2014-11-29
      • 2020-01-02
      • 2010-11-08
      • 2014-10-13
      • 2013-06-18
      • 2010-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多