2

背景:我正在开发一个已经设计了线程系统的应用程序。它远非最佳,但我目前无法对其进行返工。它不使用任何来自 .net 的较新线程构造,仅使用基本Thread对象和包装线程处理逻辑的对象。

它的一般设置是:(现在有两个组或线程类别)

  • 产生工作线程的主应用程序线程(statthread main)。

  • 工作线程。每个都有一个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() 的解决方案。

我还可以使用带有许多锁定对象的监视器——这似乎比许多等待句柄更轻量级。

另外,很抱歉这个问题很长,感谢您的阅读!

4

1 回答 1

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.
}

生成器线程还可以查询字典以查看它是否可以生成特定类型的工作者。如果它无法创建工作人员,那么它要么丢弃该工作,要么将其重新排队以供稍后检查。你多久投票一次取决于你。

WaitHandle在一个进程中拥有数百个对象并没有什么特别的问题。一堆Monitor对象可能占用更少的系统资源,但请记住 a Monitor(或 a lock)实际上是一个互斥设备。你可以做一些愚蠢的事情来让它WaitHandle在某些方面表现得像一个,但是这些技术是不明显的,这将导致难以理解和脆弱的代码。

于 2011-12-29T17:47:56.713 回答