为什么以及如何在等待MVC控制器操作之后维护MVC请求线程状态
本文关键字:MVC 维护 之后 请求 线程 状态 操作 控制器 在等待 为什么 | 更新日期: 2023-09-27 17:57:44
在下面的代码中,在等待调用之前和之后,线程id和_uow(工作单元)的散列是相同的。如果请求线程被释放,为什么继续请求线程具有相同的id?为什么与请求线程关联的_uow对象具有相同的hash id,就像线程状态被维护一样,尽管它被释放到线程池中?
public AccountController(IUow uow)
{
_uow = uow;
}
public async Task<ActionResult> Sample()
{
int id1 = Thread.CurrentThread.ManagedThreadId;
int hash1 = _uow.GetHashCode();
await SignInAsync(account, isPersistent: false);
int id2 = Thread.CurrentThread.ManagedThreadId; //same as id1
int hash2 = _uow.GetHashCode(); //same as hash1
return Content("");
}
在ASP中。NET,不能保证在await
之后在同一个线程上。但这并不意味着你一定会在另一个线程上,你仍然可以偶然地回到同一个线程。如果您正在await
执行的Task
在返回给您时已经完成,那么您也将停留在同一线程上。
但_uow
字段是另一回事:在这个代码中,它将始终保持不变(假设它不是[ThreadStatic]
字段)。这是因为在await
之后,您总是返回到相同的this
,它不绑定到任何线程。
事实上,这甚至更强:HttpContext.Current
(以及与之相关的一切)也将保持不变。这是因为ASP。NET同步上下文将负责将HTTP上下文移动到await
之后的任何新线程。
这里有两种情况。
-
SignInAsync
已同步执行。请尝试以下操作,看看是否是这样:public async Task<ActionResult> Sample() { int id1 = Thread.CurrentThread.ManagedThreadId; int hash1 = _uow.GetHashCode(); var task = SignInAsync(account, isPersistent: false); Debug.Print("completed synchronously: " + task.IsCompleted); await task; int id2 = Thread.CurrentThread.ManagedThreadId; //same as id1 int hash2 = _uow.GetHashCode(); //same as hash1 return Content(""); }
-
在
await
继续之后,相同的池线程恰好为请求的其余部分提供服务。这是非常不可能的,但仍然是可能的,尽管无论如何你都不应该依赖它。