2012-09-19 56 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

相關問題