2008-09-24 6 views
15

Meine Frage basiert auf der Übernahme einer großen Menge von Legacy-Code, über den ich nicht viel machen kann. Grundsätzlich habe ich ein Gerät, das einen Datenblock erzeugt. Eine Bibliothek, die das Gerät anruft, um diesen Datenblock zu erzeugen, aus irgendeinem Grund, den ich nicht vollständig verstehe und nicht ändern kann, selbst wenn ich das wollte, schreibt diesen Datenblock auf die Festplatte.C# -Datei lesen/schreiben Fileshare scheint nicht zu funktionieren

Dieser Schreibvorgang erfolgt nicht sofort, sondern kann bis zu 90 Sekunden dauern. In dieser Zeit möchte der Benutzer eine Teilansicht der Daten erhalten, die gerade produziert werden. Daher möchte ich einen Consumer-Thread haben, der die Daten liest, die die andere Bibliothek auf die Festplatte schreibt.

Bevor ich diesen Legacy-Code anfasse, möchte ich das Problem mit dem Code, den ich vollständig kontrolliere, nachahmen. Ich benutze C#, angeblich weil es eine Menge der Funktionalität bietet, die ich will.

In der Hersteller-Klasse habe ich diesen Code einen Zufallsdatenblock zu erstellen:

FileStream theFS = new FileStream(this.ScannerRawFileName, 
    FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read); 
//note that I need to be able to read this elsewhere... 
BinaryWriter theBinaryWriter = new BinaryWriter(theFS); 
int y, x; 
for (y = 0; y < imheight; y++){ 
    ushort[] theData= new ushort[imwidth]; 
    for(x = 0; x < imwidth;x++){ 
     theData[x] = (ushort)(2*y+4*x); 
    } 
    byte[] theNewArray = new byte[imwidth * 2]; 
    Buffer.BlockCopy(theImage, 0, theNewArray, 0, imwidth * 2); 
    theBinaryWriter.Write(theNewArray); 
    Thread.Sleep(mScanThreadWait); //sleep for 50 milliseconds 
    Progress = (float)(y-1 >= 0 ? y-1 : 0)/(float)imheight; 
} 
theFS.Close(); 

So weit, so gut. Dieser Code funktioniert. Die aktuelle Version (mit FileStream und BinaryWriter) scheint (wegen der Kopie langsamer) zu sein, File.Open mit den gleichen Optionen zu verwenden und einen BinaryFormatter auf dem ushort [] auf den Datenträger zu schreiben.

Aber dann füge ich einen Verbraucher thread:

FileStream theFS; 
if (!File.Exists(theFileName)) { 
    //do error handling 
    return; 
} 
else { 
    theFS = new FileStream(theFileName, FileMode.Open, 
     FileAccess.Read, FileShare.Read); 
      //very relaxed file opening 
} 
BinaryReader theReader = new BinaryReader(theFS); 

//gotta do this copying in order to handle byte array swaps 
//frustrating, but true. 
byte[] theNewArray = theReader.ReadBytes(
    (int)(imheight * imwidth * inBase.Progress) * 2); 
ushort[] theData = new ushort[((int)(theNewArray.Length/2))]; 
Buffer.BlockCopy(theNewArray, 0, theData, 0, theNewArray.Length); 

Jetzt ist es möglich, dass die Erklärung von theNewArray gebrochen ist, und wird eine Art von Leseüberlauf verursachen. Dieser Code kommt jedoch nie so weit, weil er beim Öffnen des neuen FileStreams immer mit einer System.IO.IOException, die besagt, dass ein anderer Prozess die Datei geöffnet hat, immer immer bricht.

Ich setze die FileAccess- und FileShare-Enumerationen wie in der FileStream-Dokumentation auf MSDN angegeben, aber es scheint, dass ich einfach nicht tun kann, was ich tun möchte (dh in einen Thread schreiben, einen anderen einlesen). Ich stelle fest, dass diese Anwendung ein wenig unorthodox ist, aber wenn ich das tatsächliche Gerät involviere, werde ich das gleiche tun müssen, aber MFC verwenden.

Auf jeden Fall, was vergesse ich? Ist das, was ich tun möchte möglich, da es in der Dokumentation als möglich angegeben ist?

Danke! MMR

Antwort

3

Ich habe keine Zeit gehabt, dies zu testen, aber ich glaube, Sie können die Flush-Methode des Binary

FileStream theFS = new FileStream(this.ScannerRawFileName, 
    FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read); 
//note that I need to be able to read this elsewhere... 
BinaryWriter theBinaryWriter = new BinaryWriter(theFS); 
int y, x; 
for (y = 0; y < imheight; y++){ 
    ushort[] theData= new ushort[imwidth]; 
    for(x = 0; x < imwidth;x++){ 
     theData[x] = (ushort)(2*y+4*x); 
    } 
    byte[] theNewArray = new byte[imwidth * 2]; 
    Buffer.BlockCopy(theImage, 0, theNewArray, 0, imwidth * 2); 
    theBinaryWriter.Write(theNewArray); 
    Thread.Sleep(mScanThreadWait); //sleep for 50 milliseconds 
    Progress = (float)(y-1 >= 0 ? y-1 : 0)/(float)imheight; 
    theBinaryWriter.Flush(); 
} 
theFS.Close(); 

Leider anrufen müssen habe ich keine Zeit gehabt, dies zu testen. Ich stieß auf ein Problem mit einer Datei, die ich erstellte, die ähnlich war (obwohl nicht genau) und ein fehlender "Flush" war der Schuldige.

34

Ihr Consumer muss FileShare.ReadWrite angeben.

Durch den Versuch, die Datei als FileShare.Read in den Verbraucher öffnen Sie sagen: „Ich möchte die Datei öffnen und lassen Sie andere es zur gleichen Zeit lesen“ ... da bereits ein Schriftsteller ist, die anrufen schlägt fehl, müssen Sie gleichzeitige Schreibvorgänge mit dem Leser zulassen.

2

Ich glaube, Chuck ist richtig, aber bedenke, dass dies nur funktioniert, weil das Dateisystem intelligent genug ist, um deine Lese-/Schreiboperationen zu serialisieren; Sie haben keine Sperre für die Dateiressource - das ist keine gute Sache :)

+0

Fair genug-- aber denken Sie daran, ich muss dies mit Legacy-Code, der fast sicher keine Dateisperren hat (und die Leute, die diesen Code geschrieben haben) tun würde dich ansehen, als wärst du verrückt dafür, dass es solche Dinge gibt). Also, wenn es deswegen bricht, ahme ich diese Pausen am besten nach. – mmr

Verwandte Themen