2 Stimmen

Wie kann ich diese Threads synchronisieren, um Datenbeschädigungen zu vermeiden?

TL;DR Version: Ich habe zwei Threads. Einer von ihnen muss möglicherweise den anderen unterbrechen(), aber nur, wenn der andere Thread gerade Daten verarbeitet, die sich auf das Objekt beziehen, das vom ersten Thread betroffen ist. Wie kann ich den zweiten Thread nur unter bestimmten Bedingungen unterbrechen?

Ich habe an einem Programm gearbeitet, das zwei Threads für die Verarbeitung von Socket-Daten und die Aktualisierung der grafischen Benutzeroberfläche mit den Informationen in Gang setzt. Die beiden Threads (topologyThread und dataThread) behandeln zwei verschiedene Aspekte meiner Anwendung, nämlich Benachrichtigungen über Topologieänderungen für unser drahtloses Sensornetzwerk und Dateninformationen für den Empfang und die Verarbeitung von Daten aus dem drahtlosen Sensornetzwerk.

Wenn Daten im dataThread ankommen, ist es möglich, dass das Netzwerkmitglied, das das Datenpaket repräsentiert, bereits vom topologyThread entfernt wurde und als solches nicht verarbeitet werden sollte. Ich dachte also, dass die Verwendung der Methode Thread.Interrupt() es mir ermöglichen würde, den dataThread sofort über Änderungen an der Topologie zu benachrichtigen und einige der Probleme zu vermeiden, die wir bei dem Versuch gesehen haben, die GUI mit Daten für ein Netzwerkmitglied zu aktualisieren, das nicht mehr verbunden ist. Meine Frage ist folgende: Wie kann ich feststellen, ob der dataThread unterbrochen werden muss? Ich möchte nicht, dass er eine Ausnahme auslöst, während er Daten für ein Netzwerkmitglied verarbeitet, das noch verbunden ist, aber ich möchte, dass er unterbrochen wird, wenn er mitten in der Verarbeitung von Daten für ein Netzwerkmitglied ist, das dann getrennt wird.

Szenario 1:

  • Die Daten kommen über den dataThread herein.
  • dataThread stellt sicher, dass das Netzwerkmitglied noch Teil des Netzwerks ist.
  • dataThread verarbeitet Daten bis zum Ende und aktualisiert GUI

Szenario 2:

  • Die Daten kommen über den dataThread herein.
  • dataThread stellt sicher, dass das Netzwerkmitglied noch Teil des Netzwerks ist.
  • Die Verbindung zum Netzwerk wurde unterbrochen, so dass keine Verarbeitung stattfindet.

Szenario 3:

  • Die Daten kommen über den dataThread herein.
  • dataThread stellt sicher, dass das Netzwerkmitglied noch Teil des Netzwerks ist.
  • dataThread beginnt mit der Verarbeitung von Daten
  • topologyThread erhält die Nachricht, dass das Netzmitglied nicht mehr angeschlossen ist und entfernt es aus der Topologie.
  • dataThread versucht, die GUI für ein Netzwerkmitglied zu aktualisieren, das nicht mehr verbunden ist.

Es ist Szenario 3, für das ich versuche, einen Code zu erstellen. In unseren Tests ist dieses Szenario, wo die Baumansicht in der Seitenleiste einfriert und die App beendet werden muss. Aber ich muss den dataThread nur unterbrechen, wenn das Objekt, das vom topologyThread betroffen ist, dasjenige ist, auf das der dataThread gerade wirkt.

Danke fürs Lesen :)

2voto

Nicholas Mancuso Punkte 11283

Sie sollten Ihre Themen nicht unterbrechen. Es könnte sicherer sein, diese mit EventWaitHandles zu programmieren, die stattdessen Signale basierend auf dem, was Sie zu erreichen versuchen, auslösen können.

1voto

mbeckish Punkte 10318

dataThread versucht, die GUI für ein Netzwerkmitglied zu aktualisieren, das nicht mehr verbunden ist.

Wie wäre es, wenn Sie topologyThread ein Flag setzen lassen, wenn das Netzwerkmitglied nicht mehr verbunden ist, und dataThread dieses Flag überprüfen lassen, bevor Sie versuchen, die GUI zu aktualisieren?

0voto

bobwienholt Punkte 17040

Interrupt() funktioniert nur, wenn der Thread blockiert ist... Sie müssen also einen anderen Mechanismus haben, um die Verarbeitung zu stoppen. Wenn Sie eine Schleife haben, in der die Daten verarbeitet werden, ist es am besten, eine Variable zu haben, die die Verarbeitung beendet, wenn sie gesetzt wird.

Ich würde es folgendermaßen machen...

Thread dataThread;
bool continueProcessing = true;
String currentNetworkMember = "";

public NotifyMemberRemoved(String member)
{
   if (currentNetworkMember == member)
   {
         continueProcessing = false;
         // Incase the thread is blocked...
         dataThread.Interrupt();
   }
}

public void ProcessingLoop()
{
    while (true)
    {
        currentNetworkMember = GetMemberToProcess();
        continueProcessing = true;
        while (continueProcessing)
        {
            try 
            {
               // Process data...
               ReadDataChunk();
               ProcessDataChunk();
            }
            catch (InterruptedException e)
            {
               // Whatever interrupted us must have set continueProcessing to false...
            }
        }
        UpdateGUI();
    }
}

0voto

yfeldblum Punkte 64211

Grundversion. Erweitern Sie sie nach Ihren Bedürfnissen.

public class CancellationInfo {
    bool _Cancel = false;
    bool _Sync = new object();
    public bool Requested { get { lock(_Sync) { return _Cancel; } }
    public void Request() { lock(_Sync) _Cancel = true; }
}

public class ThreadActions {
    private CancellationInfo Cancel = new CancellationInfo;
    public void FirstThreadAction() {
        while(true) {
            //Process some stuff.
            if(condition)
               Cancel.Request();
        }
    }
    public SecondThreadAction() {
        while(true) {
            if(Cancel.Requested)
                break;
            //Process some stuff.
        }
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X