Frage

Ich habe eine Anwendung, die zwei Threads hat.

Der erste (der Haupt-Thread), die die Daten unter Verwendung von Buchse und Aktualisierungsdatentabellen

einfängt

Die zweite Fügt die Datentabellen in der Datenbank.

Die Anwendung funktioniert gut, aber wenn es geschlossen wird, beendet der Haupt-Thread die Daten zu lesen und Abort-Methode in der zweiten Thread aufrufen, die in die Datenbank werden Einfügen kann und dies führt zu inkonsistenten Daten.

Zur Zeit verwende ich die folgende Lösung "abgebrochen wird während des Einsetzens zu überwinden"

EDIT: Nach den mächtigen Antworten änderte ich den Code

void MainThread()
{
     while(Read())
     {
        //Read Data through socket
        try
        {
           //Wait on Mutex1
           //Update Tables
        }
        finally
        {
          //Release Mutex1
        }
     }
   _isrunning = false;
   _secondThread.Join();
}
void SecondThread()
{
     while(_isrunning)
     {
        try
        {
           //Wait on Mutex1
           //Insert Tables into Database using transactions
        }
        finally
        {
           //Release Mutex1           
        }
     }
}
War es hilfreich?

Lösung

„Anrufabbruchmethode“ bedeutet Abbrechen der Faden Thread.Abort annimmt. Sie, dass nicht.

Sie Absturz effektiv Ihre App. Es gibt viele Möglichkeiten, Reiniger, dies zu tun mit Monitoren.

Dennoch sollten Sie nicht in Ihrer DB immer inkonsistente Daten, wenn Ihre Anwendung abstürzt, das ist, warum Sie DB-Transaktionen haben, die die ACID Eigenschaften.

SEHR WICHTIG EDIT Du hast gesagt: Sie keine Transaktionen aus Leistungsgründen verwenden und stattdessen mutexes verwenden. Dies ist FALSCH auf ziemlich viele Ebenen. Zum einen können Transaktionen bestimmte Operationen schneller machen, zum Beispiel versuchen, 10 Zeilen in eine Tabelle einfügen, versuchen Sie es erneut innerhalb einer Transaktion, wird die Transaktion Version schneller sein. Zweitens, was passiert, wenn / falls Ihre Anwendung abstürzt, Sie korrupte DB tun? Was passiert, wenn mehrere Instanzen Ihrer Anwendung ausgeführt werden? Oder während Sie Berichte gegen Ihre DB in Query Analyzer?

Andere Tipps

Solange beide Threads nicht als Hintergrund-Threads markiert, wird die App bis beide Threads Ausfahrt am Laufen halten. Also wirklich, alles, was Sie tun müssen, ist, jeden Thread zu erhalten separat sauber zu verlassen. Im Fall des Threads, in die Datenbank schreibt, kann dies bedeuten, einen Erzeuger / Verbraucher-Warteschlange anstrengend und einen Flag überprüft, um zu beenden.

zeigte ich einen geeigneten Erzeuger / Verbraucher-Warteschlange hier - der Arbeiter würde nur sein:

void WriterLoop() {
    SomeWorkItem item; // could be a `DataTable` or similar
    while(queue.TryDequeue(out item)) {
        // process item
    }
    // queue is empty and has been closed; all done, so exit...
}

Hier ist ein vollständiges Beispiel auf SizeQueue<> basiert - beachten Sie, dass der Prozess nicht beendet, bis der Leser und Schriftsteller haben sauber verlassen. Wenn Sie möchten, um die Warteschlange zu entwässern nicht haben (das heißt Sie früher beenden wollen, und vergessen alle ausstehenden Arbeit), dann fein -. Fügen eine zusätzliche (volatile) Flagge irgendwo

static class Program {
    static void Write(object message) {
        Console.WriteLine(Thread.CurrentThread.Name + ": " + message);
    }
    static void Main() {
        Thread.CurrentThread.Name = "Reader";
        Thread writer = new Thread(WriterLoop);
        writer.Name = "Writer";
        var queue = new SizeQueue<int>(100);
        writer.Start(queue);
        // reader loop - note this can run parallel
        // to the writer
        for (int i = 0; i < 100; i++) {
            if (i % 10 == 9) Write(i);
            queue.Enqueue(i);
            Thread.Sleep(5); // pretend it takes time
        }
        queue.Close();
        Write("exiting");
    }
    static void WriterLoop(object state) {
        var queue = (SizeQueue<int>)state;
        int i;
        while (queue.TryDequeue(out i)) {
            if(i%10==9) Write(i);
            Thread.Sleep(10); // pretend it takes time
        }
        Write("exiting");
    }
}

Ihre Mutex warten sollte ein Timeout beinhalten. Jede äußere Schleife Thread kann für einen Check ‚bitte schließen jetzt‘ Flagge. Zu, stellen Sie den ‚Bitte schließen Sie jetzt‘ Flag für jeden Thread, dann verwenden Sie ‚nachziehen‘ zu warten, für jeden Thread zu beenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top