我们的代码库中有一些Windows服务项目遵循此模型,我只是想确保它不是错误。
在此模型中,至少有一个静态“计时器”类,由System.Timers.Timer
管理,它从数据库中检索要处理的批量数据。 Semaphore
初始化为静态成员。检索一批工作后,会生成一个新的工作线程实例来处理每个行或列表项,并且线程由父计时器类的静态信号量管理。
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();
}
}
}
来自timer类的静态Semaphore
被传递给工作线程类的成员,而不是让工作线程在父计时器类的信号量上调用Release()。我认为它可以工作,因为它是一个参考类型。但我的问题是,这不会阻止垃圾收集吗?
答案 0 :(得分:1)
基本上,只要您调用worker.Run的线程正在运行,您就有了GCRoot给worker。当Run方法结束时,worker是垃圾收集的候选者(因为它不再在主线程中引用,也不在任何工作线程中引用)。
工作者获取对互斥锁的引用,但是如果它是反过来的话(只有一个静态变量持有对工作者的引用),你只会遇到问题。
所以,基本上,GC会照顾你的工作人员。
如果您的某个工作人员阻止,您可能会遇到麻烦。你最终会有一个车队,或者更糟糕的是,如果你的所有工人都被困住了,根本就没有工作。我会在worker中实现一个超时,以确保它不会阻止整个过程。