最近、async
メソッドが同期的に実行されても、とにかくタスクを返すというかなり多くの状況に遭遇しました。
public virtual Task CreateAsync(TUser user)
{
ThrowIfDisposed();
if (user == null) throw new ArgumentNullException("user");
Context.Save(user);
Context.Flush();
return Task.FromResult(0);
}
おそらく、長時間実行される可能性のある操作をスレッドにディスパッチし、まだアクティブなタスクを返して、本当に待機することをお勧めします。
public virtual Task CreateAsync(TUser user)
{
ThrowIfDisposed();
if (user == null) throw new ArgumentNullException("user");
return Task.Run(() =>
{
Context.Save(user);
Context.Flush();
});
}
ただし、TPLスレッドをスピンオフするだけでは最も安全な方法ではないのではないかと疑っています。これら2つの異なるパターンに関する解説はありますか?
メソッドが同期型の場合、最初にTask
を返さないでください。従来の同期メソッドを作成するだけです。
何らかの理由でそれが不可能な場合(たとえば、非同期インターフェースを実装している場合)Task.FromResult
を使用して完了したタスクを返すか、この場合はさらに良い場合はTask.CompletedTask
(.NET 4.6で追加)を使用するよりもはるかに良いTask.Run
の実装:
public virtual Task CreateAsync(TUser user)
{
// ...
return Task.CompletedTask;
}
APIのコンシューマーがTask
- returningメソッドが同期して実行されないことを強く気にしている場合は、Task.Run
自体を使用して確認できます。
非同期メソッドは、最終的に非同期に継続する場合でも、かなりの同期部分(最初に待機する前の部分)が存在する可能性があることに注意してください。 とにかく、非同期メソッドがTask
をすぐに返すとは限りません。
Task.FromResult
は実際にはタスクを作成または実行しませんが、返された結果をタスクオブジェクトにラップするだけです。私はUnit Tests
で個人的に使用しており、Async
メソッドをシミュレートする必要があります。もちろん、単体テストで実際のタスクを実行したくありません。
さらにTask.Run
は実際にタスクを作成し、TaskSchedulerでタスクを実行します。 Async
プログラミングをしているときはTask.Run
の使用は推奨されません。タスクではなくawait
を使用してください。 Stephen Clearyによる タスクの実行と非実行 を参照してください。