2016-05-25 14 views
2

Dies ist ein vereinfachtes BeispielWie garantiert man in Multithreading mit Ausnahmen schreiben in Datei?

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      new Thread(() => Method1()).Start(); 
      new Thread(() => Method2()).Start(); 
      Console.Read(); 
     } 

     private static void Method1() 
     { 
      using (StreamWriter sw = new StreamWriter(@"h:\data.txt")) 
      { 
       int i = 100000000; 
       while (true) 
       { 
        Thread.Sleep(100); 
        sw.WriteLine(i); 
        i++; 
       } 
      } 
     } 

     private static void Method2() 
     { 
      Thread.Sleep(6000); 
      throw null; 
     } 
    } 
} 

Stream nicht die Daten in der Datei schreibt, wenn Ausnahme zu früh und in einem anderen Thread auftritt. Datei data.txt ist zu dem Zeitpunkt leer, zu dem die Ausnahme auftritt.

ich mit dieser Situation spielte ein wenig und eine Reihe von Abhilfen gefunden:

  1. Wenn ich erhöhe die Ruhezeit für die Threads Ausnahme (und verringere Intervall zwischen den Schriften in der Datei) wird die Datei mit gefüllt werden Daten. Es ist keine Wahl, weil ich nicht weiß, wann eine Ausnahme auftritt.

  2. Als Konsequenz der vorherigen Problemumgehung kann ich die Puffergröße des Stream Writer verringern. Aber es scheint nicht funktioniert, wenn ich es zu klein einstellen - zum Beispiel, dieser Code

    FileStream fs = neuer FileStream (@ "h: \ data.txt", FileMode.Create);

    mit (Streamwriter sw = new Stream (fs, Encoding.Default, 10))

funktioniert nicht, da der erste Schreibvorgang nur dann auftritt, wenn etwa 385 ganze Zahlen im Puffer warten zu sein in Datei geschrieben.

  1. Datei wird gefüllt, wenn ich den Schreiber schließe, bevor eine Ausnahme auftritt. Aber das ist keine gute Wahl - ich muss 1 bis 10 mal pro Sekunde in die Datei schreiben. Es ist keine gute Idee, den Schreiber so oft zu öffnen und zu schließen, oder?

  2. kann ich die Ausnahme wie diese fangen

    Privat static void Method2() {

    try 
    { 
        Thread.Sleep(6000); 
        throw null; 
    } 
    catch 
    { 
        Console.WriteLine("Exception!"); 
    } 
    

    }

und alles wird in Ordnung sein - kein Programmabbruch und Datei wird von Packung zu Packung gefüllt. Aber das ist auch nicht der Fall - ich kann nicht kontrollieren, wann und wo Ausnahmen auftreten. Ich versuche überall Try-Catch zu verwenden, aber ich kann etwas verpassen.

So ist die Situation: StreamWriter Puffer ist nicht voll, Ausnahme in einem anderen Thread aufgetreten und wird nicht abgefangen, so dass die Anwendung beendet wird. Wie kann man diese Daten nicht verlieren und in eine Datei schreiben?

+2

Haben Sie versucht, den Stream zu "flush" anstatt ihn zu schließen. Das sollte sich darum kümmern, die Daten in der Datei zu speichern, während der Stream geöffnet bleibt und weitere Daten akzeptiert. – Sidewinder94

+0

Das heißt, ich würde Ihnen empfehlen, nach dem ['lock'] zu schauen (https://msdn.microsoft.com/en- us/library/c5kekkcz.aspx) Schlüsselwort und das ['Mutex'] (https://msdn.microsoft.com/en-us/library/system.threading.mutex (v = vs.110) .aspx) Objekt, das existiert, um diese Nebenläufigkeitsprobleme zu lösen – Sidewinder94

+0

Sie können jede Ausnahme im Programm abfangen, wenn Sie die Main-Methode einfach in 'try {} catch {} finally {}' blockieren und in 'finally' block wait auf die Arbeit warten Thread, um die Ausführung zu beenden – Fabjan

Antwort

1

Flushing Der Stream wird sicherstellen, dass der gesamte Inhalt in die zugrunde liegende Datei verschoben wird.

Damit wird sichergestellt, dass alle Daten gespeichert werden, nachdem Sie eine Operation abgeschlossen haben und dass eine folgende Ausnahme Ihre Anwendung nicht zu Datenverlust führt.

2

Wie ich Ihre Situation verstehe, gehen Sie davon aus, dass es irgendwo einen Fehler gibt und der Prozess kann jederzeit beendet werden. Sie möchten so viele Daten wie möglich speichern.

Sie können Flush über die StreamWriter anrufen. Dadurch werden die Daten an das Betriebssystem gesendet. Wenn Ihr Prozess beendet wird, werden die Daten eventuell vom Betriebssystem geschrieben.

Falls Sie nicht StreamWriter davon überzeugen können, aus irgendeinem Grund tatsächlich zu spülen, können Sie FileStream verwenden und dazu schreiben (Pseudocode: fileStream.Write(Encoding.GetBytes(myString))). Sie können dann die löschen oder eine Puffergröße von 1 verwenden.

Natürlich ist es am besten, wenn Sie verhindern, dass der Prozess überhaupt beendet wird. Dies ist normalerweise einfach mit Task im Gegensatz zur Verwendung von rohen Thread s.

+0

Vielen Dank für Ihre Antwort. Ich markiere es als nützlich, aber markieren Sie die Antwort von @ Sidewinder94 als akzeptiert, weil er der erste war. Ich werde auch überlegen, Aufgaben anstelle von Threads zu verwenden, aber im Moment verwendet die eigentliche Anwendung Threads, also brauche ich eine schnelle Lösung mit Threads. – Alex34758