非同期処理で書き込みと読み込みを同時にしたらどうなるか?では、同時に同じファイルに書き込もうとした場合や書き込みをしている最中に読み込みを開始した場合は例外が発生すると書いています。では書き込みと読み込みがそれぞれどのタイミングでおこなわれるかコントロールできない状態ではどうすればよいのでしょうか?

同時に同じファイルに書き込もうとすると例外が発生する

短い文字列だと書き込みはすぐ終わるので0.1秒ずつ待機しながら書き込むSaveFileメソッドを定義し、これをawaitしないで2回実行してみます。

ひとつめの書き込みをおこなっているときに二つ目の書き込みの処理がおこなわれようとしたので例外が発生してしまいました(ひとつめの書き込みは最後までおこなわれる)。

排他ロックで例外を回避する

そこでlock文をつかって定義しなおします。上記の例では同期オブジェクトとしてリストを指定しましたが、同期オブジェクトは何でもかまいません。

クリティカルセクションに入る前に、同期オブジェクトをロックします。ロックされている間、他のスレッドは同じオブジェクトをロックすることができず、アンロックされるまで待たされます。そしてロックしたスレッドはクリティカルセクションを終えた後にアンロックします。

ひとつめの書き込みをおこなっているときに二つ目の書き込みの処理がおこなわれようとした場合は終了するまで待たされます。そしてひとつめの書き込みが終了してからふたつめの書き込みが開始されます。

実行結果

書き込みと読み込みのタイミングが同じになりそうな場合も同じ方法で対応できます。

ロック中にawaitするのであればSemaphoreSlim

しかしlock文にも短所があります。ロックしているときにawaitが使えないことです。ロックはしたい、けれどもawaitもしたいというのであればlock文は使えません。そんなときはSemaphoreSlimを使うのがおすすめです。こちらはawaitが使えます。

以下のコードは同じファイルへの読み出しと書き込みが同時におきないように制御するコードです。

この場合も同時に複数の書き込みと読み出しが行なわれないように制御することができます。