简体   繁体   English

C#文件读/写fileshare似乎不起作用

[英]C# file read/write fileshare doesn't appear to work

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. 此写入不是即时的,但最多可能需要90秒。 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. 在那个时候,用户想要获得正在生成的数据的部分视图,所以我想要一个消费者线程来读取另一个库写入磁盘的数据。

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. 现在,NewArray的声明可能会被破坏,并会导致某种读取溢出。 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. 但是,这段代码永远不会那么远,因为它始终总是在尝试使用System.IO.IOException打开新的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). 我正在设置MSDN上的FileStream文档中所述的FileAccess和FileShare枚举,但看起来我无法做我想做的事情(即,在一个线程中写入,在另一个线程中读取)。 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. 我意识到这个应用程序有点不正统,但是当我得到实际的设备时,我将不得不做同样的事情,但使用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 MMR

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 already a writer that call fails, you have to allow concurrent writes with the reader. 通过尝试在消费者中将文件作为FileShare.Read打开,您说“我想打开文件并让其他人同时读取它”...因为已经有一个调用失败的编写器,您必须允许与读者并发写入。

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”是罪魁祸首。

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; 我相信Chuck是对的,但请记住,这完全有效的唯一原因是因为文件系统足够聪明,可以序列化你的读/写; you have no locking on the file resource - that's not a good thing :) 你没有锁定文件资源 - 这不是一件好事:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM