C# 作为成员传递给线程类instance=bug的静态信号量?

C# 作为成员传递给线程类instance=bug的静态信号量?,c#,multithreading,windows-services,garbage-collection,C#,Multithreading,Windows Services,Garbage Collection,我们的代码库中有几个windows服务项目遵循这个模型,我只想确保它不是一个bug 在此模型中,至少有一个静态“timer”类,由System.Timers.timer管理,该类从数据库中检索要处理的数据批。信号量初始化为静态成员。检索一批工作后,将生成一个新的工作线程实例来处理每一行或列表项,线程由父计时器类的静态信号量管理 internal class BatchTimer { private static Semaphore m_sem = new Semaphore(Settings

我们的代码库中有几个windows服务项目遵循这个模型,我只想确保它不是一个bug

在此模型中,至少有一个静态“timer”类,由
System.Timers.timer
管理,该类从数据库中检索要处理的数据批。
信号量
初始化为静态成员。检索一批工作后,将生成一个新的工作线程实例来处理每一行或列表项,线程由父计时器类的静态信号量管理

internal class BatchTimer
{
  private static Semaphore m_sem = new Semaphore(Settings.Default.ThreadCount, 
     Settings.Default.ThreadCount);
  private static System.Timers.Timer m_timer = new System.Timers.Timer();

  internal static void DoWork(object source, ElapstedEventArgs e)
  { 
    List<WorkRow> work = Work.GetBatch(Settings.Default.ObjectsPerIteration);
    foreach (WorkRow row in work)
    {
      WorkerThread worker = new WorkerThread
      {
        Semaphore = m_sem,
        Work = row
      };    
      Thread thread = new Thread(worker.Run);
      // Release() is called in finally block of WorkerThread.Run.
      m_sem.WaitOne(); 
      thread.Start();
    }
  }
}
内部类批处理计时器
{
私有静态信号量m_sem=新信号量(Settings.Default.ThreadCount,
Settings.Default.ThreadCount);
private static System.Timers.Timer m_Timer=新系统.Timers.Timer();
内部静态空隙定位销(对象源,ElapstedEventArgs e)
{ 
List work=work.GetBatch(Settings.Default.objectsperitation);
foreach(工作中的工作行)
{
WorkerThread worker=新的WorkerThread
{
信号量=m_sem,
工作=行
};    
线程线程=新线程(worker.Run);
//在WorkerThread.Run的finally块中调用Release()。
m_sem.WaitOne();
thread.Start();
}
}
}

计时器类的静态
信号量
被传递给工作线程类的成员,而不是父计时器类的信号量上的工作线程调用Release()。我认为这是假设它会工作,因为它是一个引用类型。但我的问题是,这不会阻止垃圾收集吗?

基本上,只要调用worker.Run-on的线程正在运行,您就有一个GCRoot到worker。当Run方法结束时,worker是垃圾收集的候选对象(因为它不再在主线程中被引用,也不再在任何worker线程中被引用)

worker获得了对互斥体的引用,但只有在相反的情况下才会出现问题(使用一个静态变量保存对worker的引用)

所以,基本上,GC会照顾你的员工


如果你的一个工人堵车,你可能会遇到麻烦。你最终会有一个车队,或者更糟糕的是,如果你所有的工人都被困在那里,根本没有工作做。我会在worker中实现一个超时,以确保它不会阻塞整个进程

为什么不使用threadpool而不是滥用该信号量呢?我认为这种设计起源于使用.NET 2.0时,当时threadpool.SetMaxThreads与信号量类一样新。在类似服务的1.1实现中,使用了一个自定义信号量,我认为这在逻辑上导致了在2.0升级时使用.NET信号量对象。@Ty:经过进一步挖掘,我得到了答案:信号量用于限制由于向web服务发出过多请求而导致的超时,或限制Sql Server死锁。有时我们需要将线程数限制为1(这意味着我们本来不应该选择多线程设计,但我们通常在实时发布后才知道)。根据MSDN的ThreadPool.SetMaxThreads文档,“不能将工作线程数或I/O完成线程数设置为小于计算机中处理器数的数字。”