【问题标题】:Change thread priority from lowest to highest in .net在.net中将线程优先级从最低更改为最高
【发布时间】:2012-09-20 19:12:08
【问题描述】:

我试图通过让一个线程写入链接列表而另一个线程处理链接列表来加快速度。

由于某种原因,如果我将写入链表的方法变成一个任务,而从链表读取的方法是一个低优先级线程,则程序整体完成的速度要快得多。换句话说,我在这样做时会体验到最快的结果:

 Task.Factory.StartNew( AddItems );

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

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

也许是因为第一个任务比另一个线程做的工作多,这就是为什么如果我将第二个方法设置为低优先级,所有事情作为一个整体会更快地完成。

无论如何,现在我的问题是startProcessingItems 以 ThreadPriority = Lowest 运行。我怎样才能将其优先级更改为最高?如果我在该方法中创建一个新任务,它会以低优先级运行吗?基本上 startProcessingItems 以一个列表结束,一旦它有了这个列表,我想以最高优先级开始执行。

【问题讨论】:

    标签: c# multithreading parallel-processing thread-priority


    【解决方案1】:

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

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

    读取线程可以在foreach 中调用blockingCollection.GetConsumingEnumerable() 来获取元素,而写入线程只是添加它们。读取线程会自动阻塞,所以没有必要搞乱优先级。

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

    【讨论】:

    • 每次添加或删除使用锁的项目时,我都有一个名为 listLock 的锁。但我想我会改用blockingCollection。 +1 谢谢
    • @TonoNam 锁定可以解决竞争条件问题,但 BC 更好。它的性能也可能要好得多,因为在大多数情况下,新的并发集合的性能比锁定普通集合要好得多。
    • 非常感谢。我从这里学到的东西比其他任何地方都多,哈哈。
    【解决方案2】:

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

    你的问题很大一部分是你在忙着等待:

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

    这会导致它消耗大量 CPU 周期而没有进行生产性工作,这就是为什么降低它的优先级使其执行得更快的原因。如果您不忙于等待,那么这将不再是问题。

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

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

    【讨论】:

    • 非常感谢。我将使用信号量代替。但有时在一个线程上,我必须等待更多项目出现在列表中。我使用相同的方法等到item.Next !=null 我应该同步线程吗?如果是这样,我该怎么做?我有一个线程写入链表,另一个线程从中读取并处理项目。
    • @TonoNam 正如我和 Reed 所说的,你应该使用 BlockingCollection。当您使用Take 时,它会自动等待直到有要删除的项目,并确保所有方法都显示为原子的。
    【解决方案3】:

    除了里德和瑟维所说的:

    线程优先级与进程优先级相关。

    Windows 调度程序在调度线程时间时会考虑所有其他线程。具有较高优先级的线程会占用其他线程的时间,这可能会人为地减慢系统的其余部分。这并不是说系统没有理由不给你线程更多的优先级。优先级只有在其他东西将 CPU 带离它时才会产生影响——这是有原因的。如果没有任何东西将 CPU 带离线程,它不会神奇地以最高优先级运行得更快。

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

    两个线程之间的同步开销很可能会扼杀您认为可能获得的任何性能提升。

    此外,Thread.Sleep(0) 仅将时间分配给同等优先级的线程并准备好运行——这可能导致线程饥饿。 http://msdn.microsoft.com/en-us/library/d00bd51t(v=vs.80).aspx

    【讨论】:

      猜你喜欢
      • 2013-02-11
      • 1970-01-01
      • 2014-11-26
      • 1970-01-01
      • 1970-01-01
      • 2012-06-15
      • 1970-01-01
      • 1970-01-01
      • 2020-03-22
      相关资源
      最近更新 更多