2011-12-29 75 views
2

背景: 我正在研究已经设计了线程系统的应用程序。这远非最佳,但我现在不能重做它。它不使用.net中的任何较新的线程构造,只包含基本的Thread对象,以及包装线程处理逻辑的对象。同步.NET中的多个线程4

的它的一般集合起来就是:(有两个组,或现在的线程类别)

  • 主应用程序线程(statthread主),其派生的工作线程。

  • 工作线程。每个对象都有一个Thread对象和一个工作对象,它执行所有处理/处理线程之间的边界等。每个线程运行作业,每个作业有一个JobTypeID

我需要引入第三种类型的线程,一个用于控制工人。这些控制消息将来自一个wcf Web服务(所以这个线程被隐式处理)。

的控制消息是:{暂停/恢复,列表-的-ID的}

我的目标:

我试图找出最好的方式将这些螺纹,使得同步如果一个线程正在处理一个作业,并且一条消息说要暂停这个JobTypeID的所有作业,它应该阻塞,直到发送一个简历(对于该ID)。这里的问题是,在发送消息时,没有相关的工作可能正在处理,因此不需要立即采取行动,而且我也没有工作者对象列表,所以我不能简单地迭代每个工作人员,然后执行if-matches-then-pause。

实际问题(广义) 什么将你们推荐我做了一组工作线程,一个产卵/管理器线程,和一组控制线程的同步?

事情,我已经试过

一种方法是将存储ManualResetEvent对象,每一个JobTypeID的集合,并且信号,并根据传入的消息等待他们。你对这种方法有什么看法?我无法找到任何关于在一个流程中拥有100多个等待句柄的最佳实践或内存/处理成本的信息。

另一种方法是让所有线程都等待一个对象,并等待一个同步的JobTypeIDs集合。这种方法我遇到了一些问题。使用ManualResetEvent意味着如果我恢复一个工作ID,但其他人正在等待,我必须做set(); reset();这会导致一些竞争条件(即使我尝试执行WaitHandle.SignalAndWait(x,x ))最后,我想出了一个使用Monitor.PulseAll()的解决方案。

我也可以使用带有大量锁对象的显示器 - 这看起来像是比许多等待手柄更轻量级。

此外,对于长时间的问题和感谢阅读!

+0

一些问题: 1.是否每个工作者线程都负责一个JobTypeId?或者每个线程处理任何可用的内容?当暂停消息被接受时,是否可以完全暂停一个线程中的处理作业,或者是否需要它来跳过暂停的作业,但是是否继续处理其他作业? 2.您有多少工作线程? 3.如果工作线程在暂停消息被接收时处理作业 - 你想让它完成作业还是暂停它? – ttil 2011-12-29 18:30:41

回答

2

创建一个ConcurrentDictionary<JobTypeId, ManualResetEvent>。通常,JobTypeId将不会在字典中输入。唯一一个这样的条目将存在的时候是该工作类型应该被阻止。

当该作业类型应该被阻止时,创建一个不带信号的ManualResetEvent,并将其添加到词典中,密钥为JobTypeId将被阻止。

工作线程,那么,有一个循环,看起来像这样:

while (still_have_work_to_do) 
{ 
    ManualResetEvent mevent; 
    if (PauseDictionary.TryGetValue(myJobTypeId, out mevent)) 
    { 
     // wait until the event is signaled. 
     mevent.WaitOne(); 
    } 

    // Do more processing. 
} 

的产卵线程也可以查询字典,看它是否能够产生一个特定类型的工人。如果它不能创建工作人员,那么它要么丢弃该工作,要么重新排队以便在稍后检查。你多久进行一次民意调查取决于你。

在单个进程中拥有数百个对象并没有什么特别的问题。一堆Monitor对象可能需要更少的系统资源,但请记住Monitor(或lock)确实是一个互斥设备。你可以做一些愚蠢的事情,使其在某些方面像WaitHandle一样行事,但这些技术并不明显,这会导致难以理解和脆弱的代码。