我最近遇到了相当多的情况,其中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线程并不是最安全的做法。对这两种不同的模式有什么评论吗?
发布于 2015-12-01 02:28:26
如果您的方法是同步的,那么一开始就不应该返回Task。只需创建一个传统的同步方法。
如果由于某些原因这是不可能的(例如,您实现了一些异步接口),则使用Task.FromResult返回完成的任务,甚至更好,在这种情况下,Task.CompletedTask (在.NET 4.6中添加)比在实现中使用Task.Run好得多:
public virtual Task CreateAsync(TUser user)
{
// ...
return Task.CompletedTask;
}如果你的应用程序接口的使用者非常关心Task-returning方法的不同步运行,他们可以自己使用Task.Run来确认。
您应该记住,异步方法可能有相当大的同步部分(第一个等待之前的部分),即使它们最终确实以异步方式继续。你不能假设异步方法会立即返回一个 Task 。
发布于 2015-12-01 02:37:53
Task.FromResult实际上并不创建或运行任务,但它只是将返回的结果包装在一个任务对象中。我个人在Unit Tests中使用了它,在那里我需要模拟Async方法,当然我也不想在单元测试中运行实际的任务。
此外,Task.Run实际上会在TaskScheduler上创建并运行一个任务。在进行Async编程时,不建议使用Task.Run。而是在任务上使用await。看斯蒂芬·克利里写的“do's and don't of Tasks很少”。
https://stackoverflow.com/questions/34005397
复制相似问题