2012-09-19 132 views
2

不是真的特定语言,但我有在C#:如何确保线程任务运行

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

ProcessRows()过程,直到所有行被删除数据库中删除行。在程序启动时,只要将一行添加到程序中其他位置的数据库中,就调用StartJob,以确保处理所有行而不会阻塞程序。现在如果在StartJob即将释放锁的同一时间添加一行,将不会处理该行。

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

+0

您需要将行添加到数据库中,以通知程序说它可以开始处理。你可以使用一些全球互斥体。 –

+0

“现在,如果在StartJob即将释放锁的同一时间添加一行,将不会处理它。” - 你确定?这件事发生在你身上吗? –

+0

@DanielHilgarth:这是不太可能的,但是这里存在一个理论上的竞争条件,因为'ProcessRows'在锁被释放之前完成;即使'ProcessRows'没有运行,第二个线程也可能会失败'.TryEnter'。 –

回答

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

+0

非常好,谢谢! – SStBC

相关问题