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

これで、NewArrayの宣言が壊れて、ある種の読み取りオーバーフローが発生する可能性があります。ただし、このコードは、別のプロセスがファイルを開いたことを示すSystem.IO.IOExceptionを使用して新しいFileStreamを開こうとすると常に中断するため、それほど遠くまでは行きません。

MSDNのFileStreamドキュメントに記載されているようにFileAccessとFileShareの列挙を設定していますが、やりたいこと(つまり、あるスレッドでの書き込み、別のスレッドでの読み取り)ができないようです。このアプリケーションは少し変わっていることに気づきましたが、実際のデバイスを使用する場合は、同じことを行う必要がありますが、MFCを使用します。

とにかく、私は何を忘れていますか?ドキュメントで可能な限り指定されているので、私がやりたいことは可能ですか?

ありがとう!mmr

4

3 に答える 3

38

コンシューマーはFileShare.ReadWriteを指定する必要があります。

FileShare.Readとしてファイルを開こうとすると、「ファイルを開いて、他の人に同時に読み取らせたい」と言っています...呼び出しに失敗するライターがすでに存在するため、許可する必要がありますリーダーとの同時書き込み。

于 2008-09-24T02:29:48.837 に答える
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();

申し訳ありませんが、これをテストする時間がありませんでした。私が作成していたファイルにこれに似た問題が発生しました(正確ではありませんが)。「フラッシュ」が欠落していることが原因でした。

于 2008-09-24T02:22:05.687 に答える
3

Chuckは正しいと思いますが、これが機能する唯一の理由は、ファイルシステムが読み取り/書き込みをシリアル化するのに十分スマートだからです。ファイルリソースをロックする必要はありません-それは良いことではありません:)

于 2008-09-24T02:31:22.640 に答える