Mi pregunta se basa en heredar una gran cantidad de código heredado que no puedo hacer mucho al respecto. Básicamente, tengo un dispositivo que producirá un bloque de datos. Una biblioteca que llamará al dispositivo para crear ese bloque de datos, por alguna razón que no entiendo completamente y no puede cambiar incluso si quisiera, escribe ese bloque de datos en el disco.El uso compartido de archivos de lectura/escritura de C# no parece funcionar
Esta escritura no es instantánea, pero puede tomar hasta 90 segundos. En ese momento, el usuario desea obtener una vista parcial de los datos que se están produciendo, por lo que quiero tener un hilo de consumidor que lea los datos que la otra biblioteca está escribiendo en el disco.
Antes de siquiera tocar este código heredado, quiero imitar el problema utilizando el código que controlo completamente. Estoy usando C#, aparentemente porque proporciona una gran cantidad de la funcionalidad que quiero.
En la clase productora, tengo este código la creación de un bloque al azar de los datos:
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();
Hasta ahora, todo bien. Este código funciona La versión actual (usando FileStream y BinaryWriter) parece ser equivalente (aunque más lenta, debido a la copia) a usar File.Open con las mismas opciones y un BinaryFormatter en ushort [] escrito en el disco.
Pero luego añadir un hilo consumidor:
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);
Ahora, es posible que la declaración de theNewArray se rompe, y causará algún tipo de desbordamiento de lectura. Sin embargo, este código nunca llega tan lejos, porque siempre siempre se rompe al tratar de abrir el nuevo FileStream con una excepción System.IO.IOException que indica que otro proceso ha abierto el archivo.
Estoy configurando las enumeraciones FileAccess y FileShare como se indica en la documentación de FileStream en MSDN, pero parece que simplemente no puedo hacer lo que quiero (es decir, escribir en un hilo, leer en otro). Me doy cuenta de que esta aplicación es poco ortodoxa, pero cuando involucro el dispositivo real, tendré que hacer lo mismo, pero usando MFC.
En cualquier caso, ¿qué estoy olvidando? ¿Es lo que quiero hacer posible, ya que está especificado como posible en la documentación?
Gracias! MMR
Lo suficientemente justo, pero recuerde, tengo que hacer esto con un código heredado que casi con seguridad no tiene bloqueos de archivos (y las personas que escribieron ese código te miraría como si estuvieras loco por sugerir que hay tales cosas). Entonces, si se rompe debido a eso, será mejor que imite esos descansos. – mmr