GetBuffer()を呼び出すことにより、MemoryStreamオブジェクトのデータバッファーに直接データを書き込むコードが少しあります。また、PositionプロパティとSetLength()プロパティを適切に使用および更新します。
このコードは99.9999%の確率で正しく機能します。文字通り。非常に多くの100,000回の反復ごとにのみ、それは吠えます。特定の問題は、MemoryStreamのPositionプロパティが適切な値ではなく突然ゼロを返すことです。
ただし、0をチェックし、PositionやLengthなどのMemoryStreamプロパティのログを別のメソッドに含む例外をスローするコードが追加されました。それらは正しい値を返します。同じメソッド内にロギングをさらに追加すると、このまれな状態が発生した場合、この特定のメソッド内では位置がゼロになるだけであることがわかります。
わかった。明らかに、これはスレッドの問題である必要があります。そして、おそらくコンパイラの最適化の問題です。
ただし、このソフトウェアの性質は、スケジューラーを使用した「タスク」によって編成されるため、いくつかの実際のO / Sスレッドのいずれかがいつでもこのコードを実行できますが、一度に複数のコードを実行することはできません。
したがって、通常、同じスレッドがこのメソッドに使用され続け、まれに別のスレッドが使用されることがあると思います。(スレッドIDをキャプチャして比較することにより、この理論をテストするためのアイデアをコーディングするだけです。)
次に、コンパイラの最適化により、別のスレッドが正しい値を取得することはありません。「古い」値を取得します。
通常、このような状況では、問題の変数に「volatile」キーワードを適用して、それが修正されるかどうかを確認します。ただし、この場合、変数はMemoryStreamオブジェクト内にあります。
他に何かアイデアはありますか?それとも、これは独自のMemoryStreamオブジェクトを実装する必要があることを意味しますか?
よろしくお願いいたします。ウェイン
編集:このメソッドへの呼び出しの総数をカウントし、ManagedThreadIdが最後の呼び出しと異なる回数をカウントするテストを実行しただけです。スレッドを切り替えるのはほぼ正確に50%の時間で、スレッドを交互に切り替えます。したがって、上記の私の理論はほぼ間違いなく間違っているか、エラーがはるかに頻繁に発生します。
編集:このバグはめったに発生しないため、バグが実際になくなったと感じる前に、バグなしで実行するのに1週間近くかかります。代わりに、問題の性質を正確に確認するために実験を実行することをお勧めします。
編集:現在、ロックは、MemoryStreamを使用する5つのメソッドのそれぞれでlock()ステートメントを介して処理されます。