2016-11-30 6 views
2

Dies ist das erste Mal, dass ich versucht habe, Threads in einer Anwendung zu verwenden. Ich weiß, dass diese Frage schon einmal gestellt wurde, aber von den Lösungen, die ich mir angeschaut habe, kann ich nicht sehen, wie ich sie in meiner Situation anwenden kann.C# Wie man überprüft, ob ein Thread fertig ist, bevor man einen anderen startet

Ich habe ein Programm, in dem eine Datagridview alle 60 Sekunden mit einem Timer aktualisiert wird. Die Daten stammen aus einer SQL-Datenbank. Dieser Timer startet auch einen Worker-Thread, um nach einem bestimmten Bluetooth-Gerät zu suchen und die Datenbank basierend auf den Ergebnissen im Hintergrund zu aktualisieren. Die Bluetooth-Suche ist besonders langsam, weshalb ich sie in einen Worker-Thread lege.

Mein Problem ist, manchmal ein neuer Arbeitsthread startet, bevor der vorherige fertig ist. Zumindest ist das die einzige logische Erklärung für die Fehler, die ich bekomme. Das große Give Away ist ein Datei-Locked-Fehler, wenn das einzige, was die Datei sperren kann, ein anderer Worker-Thread aus derselben Anwendung ist.

Hier ist der Code, den ich verwende, um den Hintergrund Thread zu starten.

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(); 
} 

Es scheint, dass die Lösung verwenden thread.IsAlive ist(), aber ich habe nicht in der Lage gewesen, ein gutes Beispiel zu finden. Es scheint komisch zu versuchen, nach der Existenz eines Threads zu suchen, wenn ich gerade einen neuen erstellt habe mit "Thread thread = new Thread()"

Offensichtlich vermisse ich etwas. Ich bin mit Visual Studio 2008. Vielen Dank für alle Ideen David

UPDATE

Auf der Grundlage der vorgeschlagenen Lösung von krw12572 unter ich schon versucht, diese ...

Ich änderte das! = Zu == weil ich immer noch die loadUserData() Methode im primären Thread ausführen möchte.

Im Editor bekomme ich eine grüne Unterstreichung auf "_bluetoothSearchThread" und sagt mir, dass das Feld nie zugewiesen wird und immer den Wert NULL haben wird.

Zur Laufzeit bekomme ich einen Fehler "Objektreferenz nicht auf eine Instanz eines Objekts gesetzt" in dieser Zeile.

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

Wie wird dieser Wert zugewiesen?

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(); 
    } 

aktualisieren 2

OK Ich glaube, ich es herausgefunden haben. Ich habe die! = Null wieder auf die Art und Weise geändert und den IF und Else auf die andere Seite gedreht.

Dann hatte ich mein Gehirn ein wenig zu verwenden und geändert „Gewinde“ auf „_bluetoothSearchThread“

nun der Code kompiliert und ausgeführt. Jetzt muss ich es nur testen, indem ich die Bedingungen auslöst, die den Dateisperrfehler verursachen, um zu sehen, ob ich das ursprüngliche Problem tatsächlich behoben habe. Wenn es funktioniert, markiere ich krw12572 als richtig.

Aktualisierung 2.5 Ich musste auch diese Linie bewegen, damit es nicht eine neue Instanz zu früh schafft

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

Das ist also die Arbeitslösung.

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

Hier Ihr Ergebnis: http://stackoverflow.com/questions/12949024/detecting-a-thread-is-already-running-in-c-sharp-net –

+0

@BALA Ich habe vor, dass die Lösung sehen. Es schien übermäßig komplex und ich verstand es nicht wirklich. Ich werde versuchen, es morgen blind zu verfolgen und zu sehen, ob etwas Machbares herauskommt. –

+0

Mögliches Duplikat von [Wie überprüft man, ob Thread die Ausführung beendet hat] (http://stackoverflow.com/questions/2773479/how-to-check-if-thread-finished-execution) –

Antwort

4

Wenn Sie nur ein Thread zu einem Zeitpunkt ausgeführt wird, dann können Sie ein Feld erstellen speichern Instanz Gewinde. Mit dieser Thread-Instanz können Sie überprüfen, ob sie bereits läuft oder nicht, indem Sie _threadInstance.IsAlive verwenden.

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

Ich habe das versucht. Es hatte einige Probleme. Ich habe meine Frage aktualisiert, um Ihre vorgeschlagene Lösung und die Fehlermeldungen zu berücksichtigen. Danke David –

+0

Ich aktualisierte meine Antwort. Verwenden Sie das neu erstellte Feld für die Thread-Instanz, anstatt Thread thread = new Thread (..) zu erstellen. _bluetoothSearchThread = neuer Thread (...) –

4

EDIT:

nach der Erforschung, Thread.IsAlive in Ihrem situtation verwendet, ist kein sicherer Weg, es zu tun.

sollten Sie verwenden Threa.Join()

Dokumentation:

Blockiert den aufrufenden Thread, bis die durch diese Instanz dargestellt Thread beendet wird oder die angegebene Zeit abgelaufen ist, während auf weiterhin Standard-COM ausführen und Sendmessage Pumpen.

Beispiel:

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

Wie würde ich Thread.IsAlive in meinem Beispielcode verwenden. Könnten Sie mir bitte ein paar Ideen geben? –

+0

@DavidPollard 'if (thread.isAlive) // dann was auch immer tun; ' –

+0

@DavidPollard hi, ich habe gerade die Antwort bearbeitet –

0

Sie könnten Task statt Thread verwenden möchten.

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

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

Die neue Aufgabe wird erst nach dem vorherigen ausgeführt werden.

Wenn jedoch die Tasks während der Tick keine Zeit zum Ausführen haben, werden sie sich in der Warteschlange ansammeln.

+0

Hallo Alexander, ich dachte über Aufgaben als eine Alternative nach, obwohl es keinen Sinn hat, Unteraufgaben anzuordnen. Ich verstehe jetzt, was krw12572 vorschlägt, und meine obigen Lösungen funktionieren jetzt. Um es zu testen, setze ich meinen Timer auf 10 Sekunden und ich konnte sehen, dass sich in meinen Logs überall Threads öffneten und schlossen. Mit dem oben genannten Code in ist schön und ordentlich. Thread 11 Startet und nichts anderes beginnt, bis Thread 11 beendet ist. Alle anderen Fehler, die ich jetzt erhalte, hängen nicht mit überlappenden Threads zusammen. Danke für deine Ideen. David –

Verwandte Themen