4

以前は、BinaryReader を使用して数バイトを読み取っていましたが、最近、次のエラーが発生しました。

An error has occurred: Probable I/O race condition detected while copying memory. The I/O package is not thread safe by default. In multithreaded applications, a stream must be accessed in a thread-safe way, such as a thread-safe wrapper returned by TextReader's or TextWriter's Synchronized methods. This also applies to classes like StreamWriter and StreamReader.    at System.Buffer.InternalBlockCopy(Array src, Int32 srcOffset, Array dst, Int32 dstOffset, Int32 count)
   at System.IO.FileStream.Read(Byte[] array, Int32 offset, Int32 count)
   at System.IO.BinaryReader.FillBuffer(Int32 numBytes)
   at System.IO.BinaryReader.ReadUInt16()

そのため、結果として、次のような TextReader の Synchronized メソッドを使用することにしました。

public class SafeReader
{
    private Stream m_Stream;
    private TextReader m_TextReader;
    public SafeReader(Stream stream)
    {
        m_TextReader = TextReader.Synchronized(new StreamReader(m_Stream = stream));
    }
    public Stream BaseStream
    {
        get { return m_Stream; }
    }
    public int ReadInt32()
    {
        // this doesn't even need to do anything (just has to read 4 bytes and it gets disposed of anyway);
        ReadUInt16();
        ReadUInt16();
        return -1;
    }
    public short ReadInt16()
    {
        return (short)(this.ReadUInt16());
    }
    public ushort ReadUInt16()
    {
        return BitConverter.ToUInt16(new byte[] { (byte)(m_TextReader.Read() & 0xFF), (byte)(m_TextReader.Read() & 0xFF) }, 0);
        //return (ushort)(((m_TextReader.Read() & 0xFF)) | ((m_TextReader.Read() & 0xFF) << 8));
    }
}

ただし、返される値 (独自の形式で画像をほとんど読み取ります) は正しくありません。「画像」にはわずかに青みがかった色合いがあり、これは TextReader がテキストを読み取る (そして、バイト値を読み取るだけでなく、エンコーディングを使用して文字を読み取る) という事実によって引き起こされる可能性があると感じています。

バイナリ ファイルを読み取るための TextReader の Synchronized() のような「スレッドセーフ」な方法はありますか?

4

2 に答える 2

1

試してみてくださいFile.ReadAllBytes()MemoryStream次に、 a を使用してバッファから値を抽出できます。

于 2012-12-19T04:43:19.203 に答える
1

BinaryReaderの代わりに使用できるはずですTextReaderlockアクセスするスレッドの配列を確認してください(書き込み)。

Object locker = new Object;

lock (locker) {
    //BinaryReader here
}

他のスレッドから同じものを使用します:

lock (locker) {
    //read from array (read is thread-safe though)
}

他のスレッドで書き込み操作が行われている場合、オブジェクトがロック解除されるまで待機します。

File.ReadAllBytesチャンクで読み取る必要がない場合は、 を使用することもできます。

または、Textreader で ASCII または UTF8 エンコーディングを使用します。

于 2012-12-19T04:44:09.837 に答える