C# 如何确保线程化任务已运行
不是特定于语言,但我有C语言:C# 如何确保线程化任务已运行,c#,threadpool,C#,Threadpool,不是特定于语言,但我有C语言: ProcessRows()处理并删除数据库中的行,直到删除所有行。在程序启动时,只要将一行添加到程序中其他位置的数据库中,就会调用StartJob,以确保在不阻塞程序的情况下处理所有行。现在,如果在StartJob即将释放锁的同时添加一行,则不会处理该行 如何确保处理所有行?除非添加行,否则我不希望运行ProcessRows()。不要锁定该方法;使用表示是否正在运行的标志锁定方法 一个实现可能与下面的代码类似——在本例中,我将所有逻辑移到了ProcessRows中
ProcessRows()
处理并删除数据库中的行,直到删除所有行。在程序启动时,只要将一行添加到程序中其他位置的数据库中,就会调用StartJob
,以确保在不阻塞程序的情况下处理所有行。现在,如果在StartJob
即将释放锁的同时添加一行,则不会处理该行
如何确保处理所有行?除非添加行,否则我不希望运行
ProcessRows()
。不要锁定该方法;使用表示是否正在运行的标志锁定方法
一个实现可能与下面的代码类似——在本例中,我将所有逻辑移到了ProcessRows
中,并使该方法在已经运行时立即返回
public static bool _isRunning = false;
public static void StartJob()
{
ThreadPool.QueueUserWorkItem(s => { ProcessRows(); })
}
public static void ProcessRows()
{
Monitor.Enter(_lock);
if (_isRunning)
{
Monitor.Exit(_lock);
return;
}
_isRunning = true;
while (rowsToProcess)
{
Monitor.Exit(_lock);;
// ... do your stuff
Monitor.Enter(_lock);
}
_isRunning = false;
Monitor.Exit(_lock);
}
在这种结构中,如果不设置
\u isRunning=false
,则while
循环就不可能完成-如果不是这种情况,则如果循环在方法的另一个实例启动时完成,则会出现竞争条件。同样,当调用该方法时,它将始终进入循环并在另一个实例有机会执行之前设置\u isRunning=true
。您需要向数据库中添加行的东西来向您的程序发出信号,表明它可以开始处理。您可以使用一些全局互斥。“现在,如果在StartJob即将释放锁的同时添加一行,则不会对其进行处理。”-您确定吗?这发生在你身上了吗?@DanielHilgarth:这不太可能,但是那里有一个理论上的竞争条件,因为ProcessRows
在释放锁之前完成;第二个线程可能会使.TryEnter
失败,即使ProcessRows
没有运行。@DanPuzey:你是对的。我没有正确阅读,并认为其他线程将阻塞,直到锁被释放(如Monitor.Enter)。
public static bool _isRunning = false;
public static void StartJob()
{
ThreadPool.QueueUserWorkItem(s => { ProcessRows(); })
}
public static void ProcessRows()
{
Monitor.Enter(_lock);
if (_isRunning)
{
Monitor.Exit(_lock);
return;
}
_isRunning = true;
while (rowsToProcess)
{
Monitor.Exit(_lock);;
// ... do your stuff
Monitor.Enter(_lock);
}
_isRunning = false;
Monitor.Exit(_lock);
}