C# 文件读/写文件共享似乎不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/124946/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# file read/write fileshare doesn't appear to work
提问by
My question is based off of inheriting a great deal of legacy code that I can't do very much about. Basically, I have a device that will produce a block of data. A library which will call the device to create that block of data, for some reason I don't entirely understand and cannot change even if I wanted to, writes that block of data to disk.
我的问题是基于继承了大量我无能为力的遗留代码。基本上,我有一个可以生成数据块的设备。一个库将调用设备来创建该数据块,出于某种原因,我不完全理解并且即使我想也无法更改,将该数据块写入磁盘。
This write is not instantaneous, but can take up to 90 seconds. In that time, the user wants to get a partial view of the data that's being produced, so I want to have a consumer thread which reads the data that the other library is writing to disk.
此写入不是即时的,但最多可能需要 90 秒。在那个时候,用户想要获得正在生成的数据的部分视图,所以我想要一个消费者线程来读取另一个库正在写入磁盘的数据。
Before I even touch this legacy code, I want to mimic the problem using code I entirely control. I'm using C#, ostensibly because it provides a lot of the functionality I want.
在接触这个遗留代码之前,我想使用我完全控制的代码来模拟这个问题。我使用 C#,表面上是因为它提供了很多我想要的功能。
In the producer class, I have this code creating a random block of data:
在生产者类中,我使用以下代码创建了一个随机数据块:
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 far, so good. This code works. The current version (using FileStream and BinaryWriter) appears to be equivalent (though slower, because of the copy) to using File.Open with the same options and a BinaryFormatter on the ushort[] being written to disk.
到现在为止还挺好。此代码有效。当前版本(使用 FileStream 和 BinaryWriter)似乎与使用具有相同选项的 File.Open 和正在写入磁盘的 ushort[] 上的 BinaryFormatter 等效(尽管速度较慢,因为复制)。
But then I add a consumer 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);
Now, it's possible that the declaration of theNewArray is broken, and will cause some kind of read overflow. However, this code never gets that far, because it always always always breaks on trying to open the new FileStream with a System.IO.IOException that states that another process has opened the file.
现在,NewArray 的声明可能被破坏,并且会导致某种读取溢出。然而,这段代码永远不会走那么远,因为它总是在尝试打开新的 FileStream 时总是中断, System.IO.IOException 表明另一个进程已打开文件。
I'm setting the FileAccess and FileShare enumerations as stated in the FileStream documentation on MSDN, but it appears that I just can't do what I want to do (ie, write in one thread, read in another). I realize that this application is a bit unorthodox, but when I get the actual device involved, I'm going to have to do the same thing, but using MFC.
我正在按照 MSDN 上的 FileStream 文档中的说明设置 FileAccess 和 FileShare 枚举,但似乎我无法做我想做的事情(即,在一个线程中写入,在另一个线程中读取)。我意识到这个应用程序有点非正统,但是当我涉及到实际设备时,我将不得不做同样的事情,但使用 MFC。
In any event, What am I forgetting? Is what I'm wanting to do possible, since it's specified as possible in the documentation?
无论如何,我忘记了什么?我想要做的事情是否可能,因为它在文档中被指定为可能?
Thanks! mmr
谢谢!毫米
回答by Chuck
I haven't had time to test this but I think you may need to call the Flush method of the BinaryWriter
我没有时间对此进行测试,但我认为您可能需要调用 BinaryWriter 的 Flush 方法
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();
Sorry I haven't had time to test this. I ran into an issue with a file I was creating that was similar to this (although not exact) and a missing "Flush" was the culprit.
抱歉,我没有时间对此进行测试。我在创建的文件中遇到了一个问题,该文件与此类似(虽然不准确),并且缺少“Flush”是罪魁祸首。
回答by Rob Walker
Your consumer must specify FileShare.ReadWrite.
您的使用者必须指定 FileShare.ReadWrite。
By trying to open the file as FileShare.Read in the consumer you are saying "I want to open the file and let others read it at the same time" ... since there is alreadya writer that call fails, you have to allow concurrent writes with the reader.
通过尝试在消费者中以 FileShare.Read 的形式打开文件,您是在说“我想打开文件并让其他人同时阅读它”……因为已经有一个调用失败的编写器,您必须允许与读者并发写入。
回答by Ana Betts
I believe Chuck is right, but keep in mind The only reason this works at all is because the filesystem is smart enough to serialize your read/writes; you have no locking on the file resource - that's not a good thing :)
我相信 Chuck 是对的,但请记住,这样做的唯一原因是文件系统足够智能,可以序列化您的读/写;您没有锁定文件资源 - 这不是一件好事:)