2 Stimmen

Wie synchronisiert man Threads im Socket-Server zum Schreiben in eine Datei?

Ich schreibe einen Socket-Server, der viele Client-Anfragen zum Schreiben in eine Datei erhält. Ich habe eine Arrayliste, um die Socketlistener zu speichern. Nachdem ich den Client dazu gebracht habe, bis zu 25 Anfragen zu senden, speichert der Socket-Server 25 Socketlistener und startet 25 Threads, um die Daten zu empfangen und in die Datei zu schreiben. Nach der Ausführung erhalte ich vom Server die Fehlermeldung, dass er versucht, auf die gleiche Datei zuzugreifen, die von einem anderen Prozess gesperrt ist. Ich erhalte auch Null-Referenz-Fehler. Was ist also der beste Weg, die Threads zu synchronisieren, damit alle Anfragen verarbeitet und alle Daten in die Datei geschrieben werden.

Für jede Hilfe sind wir dankbar. Danke. -CR

string data = Encoding.ASCII.GetString(byteBuffer,0, size);

if (!File.Exists(filepath))
{
    using (StreamWriter sw = File.CreateText(filepath))
    {
        sw.WriteLine(data);  
    }
}
else
{
    using (StreamWriter sw = File.AppendText(filepath))
    {
        sw.WriteLine(data);
    }
}

0voto

sll Punkte 59134

Dies ist eine klassische Erzeuger-Verbraucher-Problem können Sie das Problem leicht lösen, indem Sie Folgendes implementieren Pipeline Muster.

Im Grunde würden alle Threads in dieselbe Thread-sichere Warteschlange statt in eine Datei schreiben. Außerdem benötigen Sie einen weiteren Thread, der alle verfügbaren Anfragen nacheinander aus der gemeinsamen Sammlung liest und in eine Datei schreibt.

Mit .NET 4.X ist es einfach zu implementieren mit BlockingCollection Klasse, die eine thread-sichere Sammlung ist.

// request queue represented by a single string
var requestsQueue = new BlockingCollection<string>(); 

Die Logik zur Verarbeitung von Anfragen (die in mehreren Threads ablaufen) fügt im Grunde nur Anfragen in die Warteschlange ein:

requestsQueue.Add(request);

Der Thread/Task, der die Anfragen in eine Datei speichert, sollte die verfügbaren Anfragen auf folgende Weise verbrauchen:

using (StreamWriter sw = File.CreateText(filepath))     
{         
    foreach (var request in requestsQueue.GetConsumingEnumerable())
    {
       sw.WriteLinerequest);
    }
}

0voto

Tudor Punkte 60826

In solchen Situationen ist es besser, den Zugriff auf die Datei zu serialisieren und alle Schreibanforderungen über eine synchronisierte Warteschlange an einen separaten Thread weiterzuleiten, und zwar aus zwei Gründen:

  1. Das Schreiben/Lesen einer einzelnen Datei auf einer mechanischen Festplatte über mehrere Threads bringt keinen Leistungsvorteil (bei vielen Threads kommt es sogar zu einer Leistungsverschlechterung).
  2. Sie werden eine Menge Synchronisationsprobleme vermeiden, besonders wenn Sie eine der vordefinierten synchronisierten Warteschlangen verwenden wie ConcurrentQueue .

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