2
は考える:非同期メソッドでこの同期ラッパーが機能するのはなぜですか?
- ASP.NET/WCF Webサービス上のレガシー非非同期APIメソッドが
- 新しい非同期内部ライブラリ 使用する必要があります
- 新しい非同期のWeb APIコントローラーは
- 前進します非同期インターフェイスのみを持つ「ストレージプロバイダ」オブジェクト。そのテストは非同期に実行され、要求コンテキスト外で同期して実行されるときに渡されます。
「go async all way」オプションは、下位互換性を損なう可能性があるため、テーブルにはありません。
public class Impl {
// This works fine when used asynchronously
public Task<Guid> SaveThingAsync(Thing thingToSave) {
return await _storageProvider.saveAsync(thingToSave);
}
public Guid SaveThing(Thing thingToSave) {
// "Obviously", this code creates a deadlock when called
// from within the request context
// return SaveThingAsync(thingToSave).Result
// Not so obviously, this also creates a deadlock
// return SaveThingAsync(thingToSave)
// .ConfigureAwait(false)
// .GetAwaiter()
// .GetResult()
// This was deadlocking, but magically stopped
// return Task.Run(
// async() => await SaveThingAsync(thingToSave)
// .ConfigureAwait(false)
// ).Result;
// This one works
var saveTask = Task.Run(async() =>
await SaveThingAsync(thingToSave)));
var result = saveTask.ConfigureAwait(false).GetAwaiter().GetResult();
return result;
}
なぜですか?
これは迷惑です。昨日、最初の 'Task.Run'の例を実行するときにTaskCancelled例外が発生しました。クライアントは直接サービス参照だけでなく、インタフェースから生成されたクライアントライブラリを使用するので、SOAPインタフェースを変更するとすべてが損なわれます。 – Eris
@ErisクライアントはStephenとして言及できません。これは互換性の問題ではありません。これはここで説明されています:http://stackoverflow.com/a/22591516/122718 – usr
@Eris:最初の(コメントアウトされた) 'Task.Run'の例は本当に、本当に奇妙です。それは私の脳を曲げて、それが何をするのか理解しようとしています。 'ConfiguredTaskAwaitable'構造を渡すことは慣習的ではありません。クライアントが消費する同期インタフェースではなく、独自の(非同期の)インタフェースをサーバで使用できるはずです。残念ながら、これは(論理的に)インタフェース記述を複製します。 –