C#文件读写文件共享似乎无法正常工作

17

我的问题基于继承了大量无法改变的遗留代码。基本上,我有一个会产生数据块的设备。一个库将调用这个设备来创建该数据块,出于某些原因,即使我想要改变也完全不理解,该库会将该数据块写入磁盘。

这个写入不是瞬间完成的,可能需要长达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);

现在声明theNewArray可能存在问题,可能会导致某种类型的读取溢出。但是,由于始终在尝试使用System.IO.IOException打开新的FileStream时就会中断,因为另一个进程已经打开了该文件,所以这段代码永远不会到达那一步。

我按照MSDN上的FileStream文档设置了FileAccess和FileShare枚举,但似乎我不能做我想做的事情(即在一个线程中写入,在另一个线程中读取)。我知道这个应用程序有点不正常,但当我涉及到实际设备时,我将不得不做同样的事情,但使用MFC。

总之,我忘记了什么?我想要做的事情是否可能,因为在文档中指定为可能?

谢谢! mmr

3个回答

38

您的消费者必须指定FileShare.ReadWrite。

如果在使用者尝试以FileShare.Read方式打开文件,则表示“我想要打开文件并让其他人同时读取它”……由于已经有一个写入者,所以该调用将失败,您需要允许使用者同时进行读写操作。


3

我认为Chuck是对的,但请记住,这仅仅因为文件系统足够智能地序列化了你的读写操作才能起作用;你没有对文件资源进行锁定-这不是一个好的做法 :)


好的,但请记住,我必须处理几乎肯定没有文件锁的旧代码(编写该代码的人会认为你是疯了,如果你建议有这样的东西)。因此,如果由于这个原因它出现故障,最好模拟这些故障。 - mmr

3

我还没有时间测试,但我认为您可能需要调用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"是罪魁祸首。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接