2

不是特定于语言的,但我在 C# 中有这个:

public static void StartJob() {
    ThreadPool.QueueUserWorkItem(s => {
        if (Monitor.TryEnter(_lock)) {
            ProcessRows();
            Monitor.Exit(_lock);
        }
    }
);

ProcessRows()处理并删除数据库中的行,直到删除所有行。在程序启动时以及每当将一行添加到程序中其他地方的数据库时,StartJob都会调用它,以确保在不阻塞程序的情况下处理所有行。现在,如果在即将释放锁的同时添加一行StartJob,则不会对其进行处理。

如何确保处理所有行?ProcessRows()除非添加行,否则我宁愿不运行。

4

1 回答 1

2

不要锁定方法;使用说明您是否正在运行的标志锁定方法。

一种实现可能类似于下面的代码 - 在这种情况下,我已将所有逻辑移入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);
}

使用这种结构,如果while没有设置,循环就不可能完成_isRunning = false- 如果不是这种情况,如果循环在另一个方法实例开始时完成,就会出现竞争条件。同样,当调用该方法时,它总是会_isRunning = true在另一个实例有机会执行之前进入循环并设置。

于 2012-09-19T14:35:14.340 回答