Die beste Lösung besteht darin, ein asynchrones Schreiben mit doppelter Pufferung zu implementieren.
Schauen Sie sich die Zeitleiste an:
------------------------------------------------>
FF|WWWWWWWW|FF|WWWWWWWW|FF|WWWWWWWW|FF|WWWWWWWW|
Das 'F' steht für die Zeit zum Füllen des Puffers und das 'W' für die Zeit zum Schreiben des Puffers auf die Festplatte. Das Problem bei der Zeitverschwendung zwischen dem Schreiben von Puffern in eine Datei. Wenn Sie jedoch das Schreiben in einem separaten Thread implementieren, können Sie den nächsten Puffer sofort wie folgt füllen:
------------------------------------------------> (main thread, fills buffers)
FF|ff______|FF______|ff______|________|
------------------------------------------------> (writer thread)
|WWWWWWWW|wwwwwwww|WWWWWWWW|wwwwwwww|
F - 1. Puffer füllen
f - 2. Puffer füllen
W - 1. Puffer in Datei
schreiben w - 2. Puffer in Datei schreiben
_ - warten, bis der Vorgang abgeschlossen ist
Dieser Ansatz mit Pufferswaps ist sehr nützlich, wenn das Füllen eines Puffers eine komplexere Berechnung erfordert (daher mehr Zeit). Ich implementiere immer eine CSequentialStreamWriter-Klasse, die asynchrones Schreiben im Inneren verbirgt, sodass die Schnittstelle für den Endbenutzer nur über Schreibfunktionen verfügt.
Die Puffergröße muss ein Vielfaches der Festplattenclustergröße sein. Andernfalls wird die Leistung schlecht, wenn Sie einen einzelnen Puffer in zwei benachbarte Festplattencluster schreiben.
Den letzten Puffer schreiben.
Wenn Sie die Schreibfunktion zum letzten Mal aufrufen, müssen Sie sicherstellen, dass der aktuelle Puffer, der gefüllt wird, auch auf die Festplatte geschrieben wird. Daher sollte CSequentialStreamWriter über eine separate Methode verfügen, z. B. Finalize (Final Buffer Flush), mit der der letzte Teil der Daten auf die Festplatte geschrieben werden soll.
Fehlerbehandlung.
Während der Code den zweiten Puffer füllt und der erste in einen separaten Thread geschrieben wird, das Schreiben jedoch aus irgendeinem Grund fehlschlägt, sollte der Hauptthread diesen Fehler kennen.
------------------------------------------------> (main thread, fills buffers)
FF|fX|
------------------------------------------------> (writer thread)
__|X|
Nehmen wir an, die Schnittstelle eines CSequentialStreamWriter hat eine Write-Funktion, die bool zurückgibt oder eine Ausnahme auslöst. Wenn also ein Fehler in einem separaten Thread auftritt, müssen Sie sich diesen Status merken. Wenn Sie also das nächste Mal Write oder Finilize im Hauptthread aufrufen, wird die Methode zurückgegeben Falsch oder löst eine Ausnahme aus. Und es spielt keine Rolle, an welchem Punkt Sie aufgehört haben, einen Puffer zu füllen, selbst wenn Sie nach dem Fehler einige Daten vorausgeschrieben haben - höchstwahrscheinlich wäre die Datei beschädigt und unbrauchbar.