2016-10-22 5 views
3

で待つ場合は疑問に思う私は(コメントを参照)完璧に動作します私の基底クラスの1つに、次のコードに来た:は非同期/は、ソリューションがきれい

private static Dictionary<string, TItem> _cache; 

protected Dictionary<string, TItem> Cache 
{ 
    get 
    { 
     if (_cache == null) 
     { 
      // Instead of FillCacheAsync().Wait(); I now do the following: 
      var reset = new AutoResetEvent(false); 
      Task.Run(
       async() => 
       { 
        await FillCacheAsync(); 
        reset.Set(); 
       }); 
      reset.WaitOne(); 
     } 
     return _cache; 
    } 
} 

private async Task FillCacheAsync() 
{    
    _cache = new Dictionary<string, TItem>(); 
    await InternalCacheFillAsync();    
} 

// This is not part of the question. 
protected abstract Task InternalCacheFillAsync(); 

これは怠惰な問題に適したソリューションですプロパティをasyncとしてマークすることはできませんか? ConfigureAwait(false)の使用でさえ、私は大きな問題を抱えていました。

+0

シンプル 'FillCacheAsync()を使用しないのはなぜが(待って) '?イベントでのこの余分な作業のメリットは何ですか? – Honza

+0

@Honza:私が私の記事に書いたように、私は慎重に 'ConfigureAwait'を使い切っても重い問題につながります。 – sprinter252

+2

'AutoResetEvent'は本当に必要ではありません。より良いブロッキング解決策は 'Task.Run(()=> FillCacheAsync())。GetAwaiter()。GetResult()'です。ただし、['AsyncLazy '](https://github.com/StephenCleary/AsyncEx.Coordination)など、ブロックするのは最善ではありません。 –

答えて

4

スティーブン・クレアリーがブログでこの正確なトピックasync propertiesをカバーしています。

彼はAsyncEx libraryからAsyncLazy<T>を使用して非同期の方法でキャッシュされるキャッシュされた値プロパティへの必要性に答えるために、AutoResetEventを使用する必要がなくなり、コードを単純化することを提案します。

キャッシュされたプロパティを使用して、クラスの簡単な例:

public class SomeClass 
{ 
    static SomeClass() 
    { 
     Cache = new AsyncLazy<Dictionary<string, TItem>>(GetCacheAsync); 
    } 

    public static AsyncLazy<Dictionary<string, TItem>> Cache { get; } 

    private static Task<Dictionary<string, TItem>> GetCacheAsync() 
    { 
     .... 
    } 
}. 

そして、キャッシュされたプロパティの値へのアクセス:。

Dictionary<string, TItem> value = await SomeClass.Cache; 
+3

良いもの!だから、私の解決策はそれほど深刻ではありませんが、それでも有効です。私はStephensのlibをとにかく使用します。彼は私よりも多くのことを知っているようだ。 – sprinter252

+2

私は彼のブログについてもっと推薦することはできません、すべての記事は金の一部です。私はまだそれを読む時間がないけれども、彼の本はどちらかといえば良いはずです。 – YuvShap

+1

ちょっとした注意:できれば新しい['AsyncEx.Coordination'ライブラリ](https://github.com/StephenCleary/AsyncEx.Coordination)を使ってください。古いバージョンのAsyncExライブラリはすぐに新しいバージョンに切り替わります。 –

関連する問題