私は同じ問題に遭遇しましたが、非同期メソッドに関する 2 つの単純な事実を使用して、効率と保守性の間の妥協点を見つけることができました。
- await を実行しない非同期メソッドは同期です。
- 同期メソッドのみを待機する非同期メソッドは同期です。
これは例で示す方が良いです:
//Simple synchronous methods that starts third party component, waits for a second and gets result.
public ThirdPartyResult Execute(ThirdPartyOptions options)
{
ThirdPartyComponent.Start(options);
System.Threading.Thread.Sleep(1000);
return ThirdPartyComponent.GetResult();
}
このメソッドの保守可能な同期/非同期バージョンを提供するために、3 つのレイヤーに分割されました。
//Lower level - parts that work differently for sync/async version.
//When isAsync is false there are no await operators and method is running synchronously.
private static async Task Wait(bool isAsync, int milliseconds)
{
if (isAsync)
{
await Task.Delay(milliseconds);
}
else
{
System.Threading.Thread.Sleep(milliseconds);
}
}
//Middle level - the main algorithm.
//When isAsync is false the only awaited method is running synchronously,
//so the whole algorithm is running synchronously.
private async Task<ThirdPartyResult> Execute(bool isAsync, ThirdPartyOptions options)
{
ThirdPartyComponent.Start(options);
await Wait(isAsync, 1000);
return ThirdPartyComponent.GetResult();
}
//Upper level - public synchronous API.
//Internal method runs synchronously and will be already finished when Result property is accessed.
public ThirdPartyResult ExecuteSync(ThirdPartyOptions options)
{
return Execute(false, options).Result;
}
//Upper level - public asynchronous API.
public async Task<ThirdPartyResult> ExecuteAsync(ThirdPartyOptions options)
{
return await Execute(true, options);
}
ここでの主な利点は、変更される可能性が最も高い中間レベルのアルゴリズムが 1 回だけ実装されるため、開発者は 2 つのほぼ同一のコードを維持する必要がないことです。