第14章. シナリオ
この作品はAIを使って翻訳されている。ご意見、ご感想をお待ちしている:translation-feedback@oreilly.com
この章では、並行プログラムを書くときによくあるシナリオに対処するための、さまざまな型とテクニックを紹介する。この種のシナリオは、別の本一冊を埋め尽くすことができるので、私が最も有用だと発見したものをいくつか選んだ。
14.1 共有リソースの初期化
問題
コードの複数の部分で共有されるリソースがある。このリソースは、最初にアクセスされたときに初期化される必要がある。
解決策
.NETフレームワークには、この目的に特化した型がある:Lazy<T> 。インスタンスの初期化に使用されるファクトリー・デリゲートで、Lazy<T> 型のインスタンスを構築する。インスタンスは、Value プロパティで利用できるようになる。次のコードは、Lazy<T> 型を示している:
staticint_simpleValue;staticreadonlyLazy<int>MySharedInteger=newLazy<int>(()=>_simpleValue++);voidUseSharedInteger(){intsharedValue=MySharedInteger.Value;}
いくつのスレッドが同時にUseSharedInteger を呼び出しても、ファクトリー委譲は一度しか実行されず、すべてのスレッドが同じインスタンスを待つ。一度作成されると、インスタンスはキャッシュされ、今後Value プロパティにアクセスすると、すべて同じインスタンスが返される(前述の例では、MySharedInteger.Value は常に0 になる)。
初期化に非同期作業が必要な場合も、よく似たアプローチが使える。この場合、Lazy<Task<T>> :
staticint_simpleValue;staticreadonlyLazy<Task<int>>MySharedAsyncInteger=newLazy<Task<int>>(async()=>{awaitTask.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);return_simpleValue++;});asyncTaskGetSharedIntegerAsync(){intsharedValue=awaitMySharedAsyncInteger.Value;}
この例では、委譲はTask<int> 、つまり非同期に決定された整数値を返す。コードのいくつの部分が同時にValue を呼び出そうとも、Task<int> は一度だけ作成され、すべての呼び出し元に返される。その後、各呼び出し元は、await にタスクを渡すことで、タスクが完了するまで(非同期に)待機するオプションがある。
先行のコードは許容できるパターンだが、さらに考慮すべき点がいくつかある。一つは、非同期委譲は、Value を呼び出すどのスレッドでも実行することができ、その委譲はそのコンテキスト内で実行される。もしValue (例えば、UIスレッドとスレッドプールスレッド、または2つの異なるASP.NETリクエストスレッド)を呼び出す可能性のある異なるスレッドタイプがある場合、常にスレッドプールスレッド上で非同期委譲を実行する方がよいかもしれない。この ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access