TIPS:非同期:awaitを含むコードをロックするには?(AsyncLock編)[C#、VB]lock/SyncLockステートメントの代わりにAsyncLockクラスを使用して、await/Await演算子を含むコードで排他ロックを行う方法を解説する。4.5以降async修飾子/await演算子(VBではAsync修飾子/Await演算子、以降では省略)を使った非同期プログラミングでは、スレッド間の排他ロックにlockステートメント(VBではSyncLockステートメント)が使えない。代わりにSemaphoreSlimクラス(System.Threading名前空間)を使えば可能なのだが、コードの記述が面倒である。そこで本稿では、AsyncLockクラスを使って簡潔に記述する方法を説明する。SemaphoreSlimクラスによる排他ロックSemaphoreSlimクラスを使ってスレッド間の排他ロックを行うコードは、次のようなものだ。lockステートメントが使えない理由も含めて、詳細は「非同期:awaitを含むコードをロックするには?(SemaphoreSlim編)[C#、VB]」を参照していただきたい。FunctionSemaphoreSlimクラスを使って排他ロックするコード例(上:C#、下:VB)SemaphoreSlimクラスはスレッドアフィニティがないので、ロック中にスレッドが変わっても問題ない。C#ではSystem名前空間とSystem.Threading.Tasks名前空間をインポートしておく必要がある(以下同じ)。上のコードは、いちいちtry〜finallyステートメント(VBではTry〜Finallyステートメント)で囲まなければならず、コーディングが面倒である。lock/SyncLockステートメントのように簡潔に書けないだろうか?AsyncLockクラスで排他ロックを簡潔に記述するには?SemaphoreSlimクラスをラップしてlock/SyncLockステートメントのようなコーディングを可能にするのが、AsyncLockクラスだ。.NET」ブログで発表されたコードである。Primitives」に掲載してくれた。そのAsyncLockクラスのコードは次の通りである。Primitives」より。VBのコードは、C#のコードから筆者が翻訳した。AsyncLockクラスは、コンストラクト時にSemaphoreSlimクラスのオブジェクトを生成してメンバー変数に保持し、LockAsyncメソッドでそのSemaphoreSlimオブジェクトをロックする。LockAsyncメソッドが返したオブジェクトのDisposeメソッドが呼び出されたときに、SemaphoreSlimオブジェクトに対するロックを解放するようになっている。このAsyncLockクラスを使って冒頭のコードを書き直すと、次のようになる。FunctionAsyncLockクラスを使って排他ロックするコード例(上:C#、下:VB)あらかじめAsyncLockクラスのインスタンスを生成しておく。あとは、排他ロックしたい部分で、AsyncLockオブジェクトのLockAsyncメソッドを呼び出してusing/Usingステートメントで囲む。すると、LockAsyncメソッドを呼び出したところで排他ロックが掛かり、using/Usingステートメントから抜けるときにそのロックが解放される。try〜finallyステートメント(VBではTry〜Finallyステートメント)がusing/Usingステートメントに変わり、すっきりしたコードになった。メールマガジンをご購読ください。Japanスマートジャパン3Dモデラボキャリア@IT自分戦略研究所エンジニアライフディルバートアプリITmediaねとらぼねこらぼついトピ!ITmediaはアイティメディア株式会社の登録商標です。