我正在构建一个async
Web Api,在阅读了一些关于async
/ await
的文章后,我认为我做错了。
这是我的实际代码:
public async Task<IHttpActionResult> GetAccount(int id)
{
var i = await GetInstanceIdAsync(User, _db); //grabs a thread
...
}
public async static Task<int> GetInstanceIdAsync(IPrincipal user, Entities db)
{
var userManager =
new UserManager<ControliUser>(new UserStore<ControliUser>(db));
//next line grabs another thread but since it was called from an await
//it holds 2 threads, am I correct?
var u = await userManager.FindByNameAsync(user.Identity.Name);
return u == null ? 0 : u.InstanceId ?? 0;
}
所以我的第一个问题是,这会消耗2个线程吗?
如果答案是肯定的,那么我就采用了这种扩展方法来防止这种情况。
public static Task<int?> InstanceIdAsync(this Entities db, IPrincipal user)
{
var userManager = new UserManager<ControliUser>(new UserStore<ControliUser>(db));
return userManager.FindByNameAsync(user.Identity.Name).ContinueWith(t =>
{
if (t.IsCompleted && t.Result != null)
return t.Result.InstanceId;
return null;
});
}
我认为这个方法只消耗1个线程并减少开销,因为它保存了async
方法
我是否正确?
答案 0 :(得分:3)
所以我的第一个问题是,这消耗了2个线程吗?
没有。使用 async-await 不会产生任何额外的线程使用。相反,它在异步操作正在进行时释放线程。这意味着线程将被使用,直到调用FindByNameAsync
,然后它将被释放,只有在该操作完成后才能恢复。然后,它将在任意线程池线程上恢复操作(第一个await
之后的代码),同时保留请求上下文。
我认为这种方法只消耗1个线程并减少开销 因为它保存了一个异步方法
首先,这在WebAPI中不起作用。问题是继续只会在第一个任务完成后执行。反过来,这将通知正在进行的IO操作的同步上下文,并将导致异常。
如前所述,async方法不生成任何线程使用,它只是创建一个 状态机 ,因此它可以调用你的继续方法(在第一个await
之后的任何调用)正确。