我是一名初级开发人员,致力于为从第三方解决方案接收数据,将其存储在数据库中,然后将数据整理以供其他第三方解决方案使用的软件编写更新。我们的软件作为Windows服务运行。
查看以前版本中的代码,我看到以下内容:
static Object _workerLocker = new object();
static int _runningWorkers = 0;
int MaxSimultaneousThreads = 5;
foreach(int SomeObject in ListOfObjects)
{
lock (_workerLocker)
{
while (_runningWorkers >= MaxSimultaneousThreads)
{
Monitor.Wait(_workerLocker);
}
}
// check to see if the service has been stopped. If yes, then exit
if (this.IsRunning() == false)
{
break;
}
lock (_workerLocker)
{
_runningWorkers++;
}
ThreadPool.QueueUserWorkItem(SomeMethod, SomeObject);
}
逻辑似乎很清楚:等待线程池中的空间,确保服务尚未停止,然后增加线程计数器并使工作排队。在语句内_runningWorkers
递减,然后调用。SomeMethod()
lock
Monitor.Pulse(_workerLocker)
我的问题是:
将所有代码分组到一个单一的代码中有什么好处lock
:
static Object _workerLocker = new object();
static int _runningWorkers = 0;
int MaxSimultaneousThreads = 5;
foreach (int SomeObject in ListOfObjects)
{
// Is doing all the work inside a single lock better?
lock (_workerLocker)
{
// wait for room in ThreadPool
while (_runningWorkers >= MaxSimultaneousThreads)
{
Monitor.Wait(_workerLocker);
}
// check to see if the service has been stopped.
if (this.IsRunning())
{
ThreadPool.QueueUserWorkItem(SomeMethod, SomeObject);
_runningWorkers++;
}
else
{
break;
}
}
}
看起来,这可能会导致更多地等待其他线程,但是随后,似乎反复将其锁定在单个逻辑块中也将花费一些时间。但是,我是多线程技术的新手,因此我假设这里没有意识到其他问题。
_workerLocker
被锁定的唯一其他位置是SomeMethod()
,仅出于递减的目的_runningWorkers
,然后在外部foreach
等待_runningWorkers
登录数并返回之前将其变为零。
谢谢你的帮助。
编辑15年4月8日
感谢@delnan推荐使用信号量。代码变为:
static int MaxSimultaneousThreads = 5;
static Semaphore WorkerSem = new Semaphore(MaxSimultaneousThreads, MaxSimultaneousThreads);
foreach (int SomeObject in ListOfObjects)
{
// wait for an available thread
WorkerSem.WaitOne();
// check if the service has stopped
if (this.IsRunning())
{
ThreadPool.QueueUserWorkItem(SomeMethod, SomeObject);
}
else
{
break;
}
}
WorkerSem.Release()
被称为内部SomeMethod()
。
SomeMethod
异步调用,上面的“锁”部分将在新线程SomeMethod
开始运行之前或之后不久保留。
Monitor.Wait()
是释放并重新获取该锁,以便另一个资源(SomeMethod
在本例中为)可以使用它。在另一端,SomeMethod
获取锁,递减计数器,然后调用Monitor.Pulse()
,将锁返回给所讨论的方法。同样,这是我自己的理解。
Monitor.Wait
释放锁。我建议看一下文档。