2017-09-15 32 views
1

は、私は、非同期メソッドがあります。非同期および同期方法

public async Task<Foo> GetFooAsync(); 

をそして私はその同期バージョンが必要です。このような何か:

public Foo GetFoo(); 

それは良い考えですか、このメソッドは任意の非自明な問題を抱えている私は本当に全くGetFooAsyncのコードを書き換えることはしたくないと私は、このような

public Foo GetFoo() 
{ 
    return GetFooAsync().GetAwaiter().GetResult(); 
} 

として何かをしたいですか?私が同期コンテキストでGetFooAsync().Resultを使用するかどうか分かっているように、私はデッドロックに直面する可能性があります。しかし、GetFooAsync().GetAwaiter().GetResult()はどうですか?

+4

''返すGetFooAsync()。結果; ''? –

+1

'.Result'を使わないでください。' .GetAwaiter()。GetResult() 'は集約例外を処理するため、GetResult()は使用しません。 – Lloyd

+3

同期バージョンが必要な場合は、shyncオーバーロードを個別に追加してください。 – Rahul

答えて

4

同期/非同期コードを混ぜるとデッドロックが発生するas described in this article( 'Async all way')。

問題はTask継続が実行され、現在のSynchronizationContextに依存します。同期が現在Wait()/Result/GetResult()への呼び出しによってブロックされたのと同じスレッド上にスケジュールされることを意図されている場合、あなたは、同期バージョンをしたい場合は、順序で別々の方法のshynchronousオーバーロードを追加するトラブル

3

に実行していますSOC(分離の懸念)を持つこと。 I.c、あなたはすでにあなたがは、例えば、同期実行中のメソッドの背後にある非同期実装を隠すべきではありません

public Foo GetFoo() 
{ 
    ///code body 
} 
+0

一般に、同期バージョンを最初に書き出し、async(多分フラグ付き)用に変更するか、同期バージョンを単純にワーカースレッドにラップして非同期にすることはできますか? – samosaris

+3

@サマサリン、いいえ、回答に記載されているように、常にメソッドの2つの異なるバージョンを持つ方が良いですし、.NET BCLの場合でも同じことが見られます – Rahul

3

を行っているとして、以下のような過負荷を追加すると、

Task.Run(async() => await GetFooAsync()); 

同期バージョンを個別に実装するか、コンシューマに明示的にGetFooAsyncを同期させます。 問題は、タスクを実行するとワーカースレッドが消費され、使用可能なワーカーのプールには制限があることです。ブロックするコードを実行する可能性があります。したがって、APIコンシューマは、同期実装が非同期に処理されることを認識する必要があります。

+0

名前を 'public Foo SynchronisedGetFooAsync()'に変更したらどうなりますか?そのため、消費者は非同期メソッドの単なるラッパーを知ることができます。 –

関連する問題