2008-09-24 2 views
15

Мой вопрос основан на наследовании большого количества устаревших кодов, о которых я не могу многого говорить. В принципе, у меня есть устройство, которое будет генерировать блок данных. Библиотека, которая будет вызывать устройство для создания этого блока данных, по какой-то причине я не совсем понимаю и не могу изменить, даже если захочу, записывает этот блок данных на диск.Файл чтения/записи файлов C# не работает

Эта запись не мгновенная, но может занять до 90 секунд. В это время пользователь хочет получить частичное представление данных, которые производятся, поэтому я хочу иметь потребительский поток, который считывает данные, которые другая библиотека записывает на диск.

Прежде чем я коснусь этого устаревшего кода, я хочу подражать проблеме с помощью кода, который я полностью контролирую. Я использую C#, якобы потому, что он предоставляет много функций, которые я хочу.

В классе производителя, у меня есть этот код, создавая случайный блок данных:

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(); 

До сих пор, так хорошо. Этот код работает. Текущая версия (с использованием FileStream и BinaryWriter) представляется эквивалентной (хотя и медленной, из-за копии) с использованием File.Open с теми же параметрами и BinaryFormatter на ushort [] записывается на диск.

Но тогда я добавляю потребительскую тему:

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); 

Теперь, возможно, что декларация theNewArray нарушается, и будет вызывать какое-то переполнение чтения. Однако этот код никогда не заходит так далеко, потому что он всегда всегда ломается, пытаясь открыть новый FileStream с помощью System.IO.IOException, в котором говорится, что другой процесс открыл файл.

Я устанавливаю перечисления FileAccess и FileShare, как указано в документации FileStream на MSDN, но кажется, что я просто не могу делать то, что хочу (т.е. писать в одном потоке, читать в другом). Я понимаю, что это приложение немного неортодоксально, но когда я получаю фактическое устройство, мне придется делать то же самое, но с использованием MFC.

В любом случае, что я забыл? Это то, что я хочу сделать возможным, так как это указано в документации?

Спасибо! MMR

ответ

3

У меня не было времени, чтобы проверить это, но я думаю, что вам может понадобиться вызвать метод Flush из BinaryWriter

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(); 

К сожалению у меня не было времени, чтобы проверить это. Я столкнулся с проблемой с созданным мной файлом, который был похож на этот (хотя и не точным), и недостающий «Flush» был виновником.

34

Ваш потребитель должен указать FileShare.ReadWrite.

При попытке открыть файл как FileShare.Read у потребителя вы говорите: «Я хочу открыть файл и позволить другим читать его одновременно» ... поскольку есть уже писатель, который звонит не удалось, вы должны разрешить одновременную запись с читателем.

2

Я считаю, что Чак прав, но имейте в виду, единственная причина, по которой это работает, заключается в том, что файловая система достаточно умна, чтобы сериализовать ваши операции чтения/записи; у вас нет блокировки на файловом ресурсе - это не очень хорошо :)

+0

Достаточно справедливо - но помните, что я должен сделать это с устаревшим кодом, который почти наверняка не имеет никаких файловых блокировок (и людей, которые написали этот код будет смотреть на вас, как на орехи, чтобы предположить, что есть такие вещи). Так что, если это ломается из-за этого, я лучше всего имитирую эти перерывы. – mmr 2008-09-25 17:20:34

Смежные вопросы