asp.net-mvc - 从 Session_Start 调用异步方法

标签 asp.net-mvc session asynchronous async-await .net-4.5

如何从 Global.asax 中的 Session_Start 调用 async 方法?

全局.asax:

    protected async Task Session_Start(object sender, EventArgs e)
    {            
        Session.Timeout = 10;

        // Do some asynch work
        await repository.SetStatsInfo(System.DateTime.Now);            
    }

异步方法:

    public async Task SetStatsInfo(DateTime time)
    {
        using (ApplicationDBContext db = new ApplicationDBContext())
        {
            // Do stuff (update visitors counter in db) ..

            await db.SaveChangesAsync();

        }
    }

我可以同步运行它(定义void Session_Start等),这是有效的,但更喜欢异步方式,这样访问数据库就不会阻塞。

像这样使用'async Task' for Session_Start运行,代码不会被执行, 未命中 session_start 内的断点。

最佳答案

据我了解,ASP 有一个指定线程,它是唯一有权访问 HttpContext.Current 对象并进而访问 Session 的线程 (HttpContext.Current.Session) 非常类似于 Windows 应用程序中的 UI 线程。因此,在 Session_Start 回调中执行 .Wait().Result 将会给您带来未知的结果和/或导致进程死锁。

似乎有很多方法来管理任务的执行线程,主要的方法是通过 TaskScheduler 类 https://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler(v=vs.110).aspx#Sync 指定您的任务在特定的同步上下文中运行。

但是,由于 Task 类被设计为实现来自 APM(异步编程模型)模式的 IAsyncResult,这使得 Task 向后兼容较旧的 APM 模式代码(根据我的理解) ASP 最初是建立在)。不过,这需要一些集成工作https://blogs.msdn.microsoft.com/mazhou/2011/10/04/the-asynchronous-programming-models/ (标准 APM)。

.Net 4.5 引入了一个很好的任务包装器 (EventHandlerTaskAsyncHelper),利用 APM 风格的 HttpApplication 来执行异步操作以支持。它满足访问Session对象的所有要求,并在HttpApplication中正确执行:

public override void Init()
{
    base.Init();
    //EventHandlerTaskAsyncHelper Wraps the task call in an APM-style BeginEventHandler, EndEventHandler
    var wrapper = new EventHandlerTaskAsyncHelper(AsyncSessionStart);
    this.AddOnAcquireRequestStateAsync(wrapper.BeginEventHandler, wrapper.EndEventHandler);
}

private async Task AsyncSessionStart(Object sender, EventArgs evtArgs)
{       
    //The only caveat is we have to check IsNewSession to see if it was created in this call
    //This doesn't need to be applied for other AddOn*Async wire-ups
    if (!Session.IsNewSession)
        return;

    await doSomethingAsync();
}

//I recall seeing something that for session state to be active, this callback has to be declared, even if empty
protected void Session_Start(object sender, EventArgs e)
{
    //Synchronous session
}

关于asp.net-mvc - 从 Session_Start 调用异步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38956394/

相关文章:

c# - View 模型验证与领域模型验证

PHP 无法从 NFS 共享中读取 session

ios - 具有异步闭包变量的结构函数

winapi - I/O 完成端口 vs. RegisterWaitForSingleObject?

javascript - 使用外部文件重构 React 的 componentDidMount() 中的嵌套异步回调

javascript - 如何将整套模型附加到formdata并在MVC中获取

asp.net-mvc - 在 ASP.NET MVC 中上传多个图像 + 文本字段

session - Tomcat 中的 crossContext 属性有什么作用?它是否启用 session 共享?

java - hibernate +OSIV。 2 笔交易。可重复读取

javascript - 如何刷新ViewBag?