【问题标题】:Why and how is MVC request thread state maintained after await on a MVC controller action?为什么以及如何在等待 MVC 控制器操作后维护 MVC 请求线程状态?
【发布时间】:2014-04-13 04:13:54
【问题描述】:

在以下代码中,_uow(工作单元)的线程 ID 和哈希值在调用 await 之前和之后是相同的。如果请求线程被释放,为什么延续请求线程的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("");
}

【问题讨论】:

    标签: c# asp.net-mvc async-await


    【解决方案1】:

    在 ASP.NET 中,不能保证您在 await 之后位于同一个线程上。但这并不意味着你一定会在另一个线程上,你仍然可以偶然回到同一个线程。如果Task you're awaiting 在返回给你时已经完成,你也会留在同一个线程上。

    但是_uow 字段是另一回事:在这段代码中它始终保持不变(假设它不是[ThreadStatic] 字段)。那是因为在await 之后,你总是会回到同一个this,这与任何线程无关。

    实际上,这更强大:HttpContext.Current(以及与之相关的所有内容)保持不变。这是因为 ASP.NET 同步上下文将负责将 HTTP 上下文移动到 await 之后的任何新线程。

    【讨论】:

      【解决方案2】:

      这里有两种可能的情况。

      • 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 延续之后,恰好相同的池线程为请求的其余部分提供服务。这是非常不可能的,但仍然有可能,尽管无论如何你都不应该依赖它。

      【讨论】:

      猜你喜欢
      • 2013-03-11
      • 2023-03-08
      • 1970-01-01
      • 2014-05-15
      • 1970-01-01
      • 1970-01-01
      • 2014-08-03
      • 2017-10-08
      • 1970-01-01
      相关资源
      最近更新 更多