2010-10-27 159 views
3
public void EnqueueTask(int[] task) 
{ 
    lock (_locker) 
    { 
     _taskQ.Enqueue(task); 
     Monitor.PulseAll(_locker); 
    } 
} 

所以,在这里,我将元素添加到我的队列中,而不是线程对它们进行一些处理。如何将项目异步添加到队列中?如何在C#中将队列添加到队列<T>?

+0

您使用的是什么版本的.net? – 2010-10-27 08:37:20

+0

我决定使用ConcurrentQueue (新的.NET 4集合) – 2010-10-27 09:05:45

回答

2

如果你使用.net V4看看新的线程安全集合,他们大多没有阻塞,所以将适当地避免需要一个异步添加。

+0

ConcurrentQueue 2010-10-27 08:57:51

+0

顺便说一句,谢谢:)。我有来自.NET 4的新线程安全集合的书签,并且您帮助我记住它们) – 2010-10-27 09:07:55

0

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

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

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

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

2

由于您使用队列<T>(推荐),因此无法使用Queue.Synchronized。

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

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

这也意味着事情离开队列的东西已经在另一个线程,因为你使用“PulseAll”来弱化线程。

E.g.

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); 
    } 
} 
+0

您是对的,我在许多线程中处理队列中的任务,并希望添加异步添加元素的功能。谢谢为您的答复,但我决定使用“ConcurrentQueue ”,恕我直言,我最邪恶的方式:) – 2010-10-27 09:01:05

+0

问题是为什么你不想添加该功能? 会发生什么是你开始一个线程添加一个元素,并且线程再次在几毫秒内死亡,因为“添加”一个元素(如果正确)将不会阻止你。不得不启动一个新线程并启动它可能需要更长的时间,而不仅仅是同步进行。显然你身边的某个地方有一个或多个“线程”,这些线程又会增加一些东西,例如通过用户点击一个按钮或端口上的数据传入等,但你最有可能在那里处理。将“Enqueue”方法扩展为Async不会使您受益。 – Jens 2010-10-27 09:07:07

+0

这不是我的决定,任务是关于这个) – 2010-10-28 07:22:08

0

您问题中的代码似乎表明您正试图实施阻塞队列。在Queue<T>.Enqueue之后,我从Monitor.PulseAll拨打电话。这是发出去队列线程的正常模式。所以如果是这种情况,那么最好的选择是使用.NET 4.0中可用的BlockingCollection类。