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

时间:2020-03-06 14:38:16  来源:igfitidea点击:

我的问题基于继承很多我不能做的遗留代码。基本上,我有一台可以产生数据块的设备。由于某种原因(由于我不完全理解并且即使我想也无法更改),将调用该设备来创建该数据块的库将该数据块写入磁盘。

此写操作不是瞬时的,但可能需要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(具有相同的选项)以及将ushort []上的BinaryFormatter写入磁盘等效(尽管由于复制而变慢)。

但是然后我添加了一个消费者线程:

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

现在,NewArray的声明可能已损坏,并会导致某种类型的读取溢出。但是,此代码从没有走过这么远,因为在尝试使用System.IO.IOException来打开新的FileStream时总是总是中断,该操作指出另一个进程已打开该文件。

我正在按MSDN上的FileStream文档中所述设置FileAccess和FileShare枚举,但看来我只是做不到我想做的事情(即,在一个线程中编写,在另一个线程中读取)。我意识到这个应用程序有点不合常规,但是当我涉及到实际的设备时,我将不得不做同样的事情,但是要使用MFC。

无论如何,我忘记了什么?由于文档中已尽可能地指定了我想做的事情吗?

谢谢!
毫米波

解决方案

我还没有时间进行测试,但是我认为我们可能需要调用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();

对不起,我还没来得及测试。我遇到一个与我正在创建的文件类似的问题(尽管不完全正确),而罪魁祸首是缺少" Flush"。

使用者必须指定FileShare.ReadWrite。

通过尝试以FileShare.Read的形式打开文件,在使用者中我们说的是"我想打开文件并让其他人同时读取" ... ...由于已经存在调用失败的编写器,因此我们必须允许与读者并发写入。

我相信Chuck是正确的,但请记住,这唯一可行的唯一原因是文件系统足够智能,可以序列化读/写;我们没有锁定文件资源不是一件好事:)