2012-09-20 48 views
2

我试图通过让一个线程写入链接列表和另一个线程处理链接列表来加快速度。在.net中将线程优先级从低到高更改为:

由于某种原因,如果写入链接列表的方法将其设置为一个任务,并且从链接列表中读取一个低优先级的线程的方法,程序会以更快的速度完成。换句话说,我experiense fastests结果时做:

Task.Factory.StartNew(AddItems); 

new Thread(startProcessingItems) { Priority = ThreadPriority.Lowest }.Start(); 

while(completed==false) 
    Thread.Sleep(0); 

也许是因为第一个任务是做的比其他线程,这就是为什么一切作为一个整体将更快地完成,如果我设定的第二种方法低优先级这么多的工作。

反正现在我的问题是startProcessingItems使用ThreadPriority =最低运行。我怎么能改变它的优先级最高?如果我在该方法中创建新的任务,它将以低优先级运行吗?基本上startProcessingItems以列表结束,一旦它有了这个列表,我想开始以最高优先级执行。

回答

5

这不是一个好方法。首先,LinkedList<T>不是线程安全的,因此写入并在两个线程中读取它将导致竞争条件。

更好的方法是使用BlockingCollection<T>。这允许您添加项目(生产者线程)和读取项目(消费者线程),而不必担心线程安全性,因为它完全是线程安全的。

读线程可以在foreach中调用blockingCollection.GetConsumingEnumerable()来获取元素,写线程只是添加它们。读线程将自动阻止阻止,所以不需要混淆优先级。

当写入线程“完成”时,您只需调用CompleteAdding,这将使读取线程自动完成。

+0

我有一个名为listLock的锁,每当我添加或删除一个使用锁的项目时。但我想我会使用blockingCollection来代替。 +1谢谢 –

+1

@TonoNam Locking可以解决比赛条件问题,但BC会更好。它也可能会表现得更好,因为在大多数情况下新的Concurrent集合比锁定正常集合要好得多。 –

+0

非常感谢。我从这里学到的东西比任何其他地方都要多。 –

2

通过改变固有设计,而不是通过更改线程/进程优先级,可以提高程序的性能。

你的问题的很大一部分是你正在做一个busywait:

while(completed==false) 
    Thread.Sleep(0); 

这导致它消耗大量的CPU周期为没有生产工作,这也是为什么降低它的优先级使它执行更快。如果你没有等待,那么这将不再是一个问题。

正如里德所说,BlockingCollection是为这种情况量身定做的。您可以让生产者线程使用Add添加项目,使用Take的消费者线程知道如果没有更多项目需要移除,该方法将简单地阻止。

您还可以存储您创建的Task,并使用Task.ResultTask.Wait让主线程等待另一个任务完成(不浪费CPU周期)。 (如果你正在使用线程直接就可以使用Join。)

+0

非常感谢。我将使用信号量来代替。但有时在一个线程中,我不得不等待更多的项目在列表中。我使用相同的方法等到'item.Next!= null'应该同步线程吗?如果是的话我怎么能这样做?我有一个线程写入链接列表,另一个线程正在读取并处理项目。 –

+1

@TonoNam由于里德和我都说过,你应该使用'BlockingCollection'。当你使用'Take'时,它会自动等待,直到有一个项目被移除,并且它将确保所有的方法看起来都是原子的。 – Servy

2

除了什么里德和Servy说:

线程优先级相对于进程的优先级。

Windows调度程序在为线程调度时间时会考虑所有其他线程。具有更高优先级的线程需要时间远离其他线程,这可能会人为拖慢系统的其余部分。这不像系统没有理由不给你线程更多的优先权。如果别的东西使CPU远离它,优先级只会产生影响 - 这是出于某种原因。如果没有任何东西将CPU从线程中分离出来,那么优先级最高的时候它不会神奇地运行得更快。

将线程优先级设置为Highest几乎总是错误的做法。

可能两个线程之间的同步开销将会消除您认为可能会获得的任何性能增益。

此外,Thread.Sleep(0)只会放弃时间给同等优先级的线程,并准备运行 - 这可能会导致线程匮乏。 http://msdn.microsoft.com/en-us/library/d00bd51t(v=vs.80).aspx

相关问题