2016-11-30 97 views
2

這是我第一次嘗試在應用程序中使用線程。 我知道這個問題之前已經問過,但我看過的解決方案我看不到如何將它們應用於我的情況。c#如何檢查一個線程是在開始另一個線程之前完成

我有一個程序,每60秒刷新一次定時器上的datagridview。數據來自SQL數據庫。此計時器還啓動工作線程以查找特定的藍牙設備,並根據其在後臺發現的數據更新數據庫。藍牙查找速度特別慢,這就是爲什麼我把它放在工作線程中的原因。

我的問題是,有時一個新的工作線程在前一個線程完成之前就開始了。至少這是我得到的錯誤的唯一合理解釋。當可以鎖定文件的唯一事情是來自同一應用程序的另一個工作線程時,大放棄是文件鎖定錯誤。

這是我用來啓動後臺線程的代碼。

private void timerScreenRefresh_Tick(object sender, EventArgs e) 
{ 
    if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", ""); 

    // If the user is not on a Remote desktop connection 
    if (!remoteDesktopUser) 
    { 

     // Run the Bluetooth Search in a worker thread 
     Thread thread = new Thread(new ThreadStart(this.checkProximity)); 
     thread.IsBackground = true; 
     thread.Start(); 
    } 

    // Load User Data from the DB and display on the screen 
    loadUserData(); 
} 

這似乎是解決方案是使用thread.IsAlive(),但我一直沒能找到一個很好的例子。當我剛剛創建一個新線程時,嘗試檢查線程的存在是很奇怪的,「Thread thread = new Thread()」

顯然我錯過了一些東西。我使用Visual Studio 2008的 感謝您的任何想法 大衛

UPDATE通過krw12572下面我試圖此基礎上提出的解決方案

...

我改變了!=來==,因爲我仍然希望每次都在主線程中運行loadUserData()方法。

在編輯器中,我在「_bluetoothSearchThread」上得到一個綠色下劃線,告訴我該字段永遠不會被分配,並且總是有NULL值。

在運行時,我得到一個「對象引用未設置爲對象的實例」錯誤在這一行上。

if (_bluetoothSearchThread == null && _bluetoothSearchThread.IsAlive) 

該值是如何分配的?

private Thread _bluetoothSearchThread; 
    private void timerScreenRefresh_Tick(object sender, EventArgs e) 
    { 
     if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", ""); 

     // Check if Worker Thread is already running. 
     if (_bluetoothSearchThread == null && _bluetoothSearchThread.IsAlive) 
     { 
      if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "Previous Worker Thread not running"); 

      // If the user is not on a Remote desktop connection 
      if (!remoteDesktopUser) 
      { 
       // Check if the users mobile phone is within range 
       // Run the Bluetooth Search in a worker thread 

       Thread thread = new Thread(new ThreadStart(this.checkProximity)); 
       thread.IsBackground = true; 
       thread.Start(); 
      } 
     } 
     else 
     { 
      if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "Worker Thread still running don't start another one"); 
     } 

     // Load User Data from the DB and display on the screen 
     loadUserData(); 
    } 

更新2

好,我想我已經想通了。 我將!= Null改回原來的樣子,並將IF和Else繞過另一個方向。

然後,我不得不用我的大腦有點,改變了「線」到「_bluetoothSearchThread」

現在代碼可以編譯和運行。現在我只需要通過觸發導致文件鎖定錯誤的條件來測試它,看看我是否已經真正解決了原始問題。如果有效,我會將krw12572答案標記爲正確。

更新2。5 我也不得不移到此行,它不會創建一個新的實例太快

_bluetoothSearchThread = new Thread(new ThreadStart(this.checkProximity)); 

所以這是可行的解決方案。

private Thread _bluetoothSearchThread; 
    private void timerScreenRefresh_Tick(object sender, EventArgs e) 
    { 
     if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", ""); 


     // Check if Worker Thread is already running. 
     if (_bluetoothSearchThread != null && _bluetoothSearchThread.IsAlive) 
     { 
      // Thread is still running. Just log it and move on. 
      if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "******** Worker Thread still running don't start another one *********"); 
     } 
     else 
     { 
      if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "Previous Worker Thread not running"); 

      // If the user is not on a Remote desktop connection 
      if (!remoteDesktopUser) 
      { 
       // Check if the users mobile phone is within range 
       // Run the Bluetooth Search in a worker thread 
       _bluetoothSearchThread = new Thread(new ThreadStart(this.checkProximity)); 
       _bluetoothSearchThread.IsBackground = true; 
       _bluetoothSearchThread.Start(); 
      } 
     } 

     // Load User Data from the DB and display on the screen 
     loadUserData(); 
    } 
+0

在這裏你的結果:http://stackoverflow.com/questions/12949024/detecting-a-thread-is-already-running-in-c-sharp-net –

+0

@BALA我以前見過這個解決方案。它似乎過於複雜,我並不真正瞭解它。我會試着明天盲目跟隨它,看看是否有可行的東西出來。 –

+0

可能重複[如何檢查線程是否執行完成](http://stackoverflow.com/questions/2773479/how-to-check-if-thread-finished-execution) –

回答

4

如果你想只有一個線程運行的時間,那麼你可以創建一個字段來存儲線程實例。使用該線程實例,您可以使用_threadInstance.IsAlive來檢查它是否已在運行。

private Thread _bluetoothSearchThread; 
private void timerScreenRefresh_Tick(object sender, EventArgs e) 
{ 
    if(_bluetoothSearchThread != null && _bluetoothSearchThread.IsAlive) 
     return;  //It means one thread is already performing the search operation. 

    if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", ""); 

    // If the user is not on a Remote desktop connection 
    if (!remoteDesktopUser) 
    { 

     // Run the Bluetooth Search in a worker thread 
     _bluetoothSearchThread = new Thread(new ThreadStart(this.checkProximity)); 
     _bluetoothSearchThread.IsBackground = true; 
     _bluetoothSearchThread.Start(); 
    } 

    // Load User Data from the DB and display on the screen 
    loadUserData(); 
} 
+0

我試過了。它有一些問題。我更新了我的問題,以包含您提出的解決方案和錯誤消息。謝謝大衛 –

+0

我更新了我的答案。而不是創建Thread thread = new Thread(..),爲線程實例使用新創建的字段。 _bluetoothSearchThread =新主題(...) –

4

編輯:

研究,在您使用situtation後Thread.IsAlive是不是一種安全的方式來做到這一點。

您應該使用Threa.Join()

文檔:

塊調用線程,直到這個 實例所表示的線程終止或特定的時間之後,在繼續 執行標準的COM和SendMessage消息抽水。

例子:

while(!currentThread.Join(0)) //should specify the time if you dont want it to be blocking. 
{ 
    ///thread is ongoing 
} 
Console.WriteLine("while loop has breaked! so the thread is finished!"); 
+0

我如何在我的示例代碼中使用Thread.IsAlive。你能給我一些想法嗎? –

+0

@DavidPollard'if(thread.isAlive)//然後做任何事情; ' –

+0

@DavidPollard嗨,我剛剛編輯了aswer –

0

你可能想使用Task而不是Thread

// Create dummy task 
Task task = Task.Run(() => { }); 

private void timerScreenRefresh_Tick(object sender, EventArgs e) 
{ 
    ... 
    // add continuation to current task 
    task.ContinueWith(t => checkProximity); 
    ... 
} 

新任務將只在前一個之後執行。

但是,如果任務在Tick期間沒有時間運行,它們將累積在隊列中。

+0

嗨亞歷山大,我正在考慮任務作爲替代,雖然我沒有點排隊子任務。我現在明白krw12572的建議和我的解決方案現在的工作。爲了測試,我將計時器記號設置爲10秒,我可以從日誌中看到它正在打開和關閉所有地方的線程。上面的代碼是非常有序的。線程11開始,直到線程11完成後纔開始。所以現在我得到的任何其他錯誤都與重疊的線程無關。感謝您的想法。大衛 –

相關問題