从Session_Start调用异步方法

时间:2016-08-15 13:53:31

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

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

的Global.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();

        }
    }

我可以同步运行它(定义{{​​1}}等),但它更喜欢异步方式,以便命中数据库不会阻塞。

对于void Session_Start使用'async Task'运行,代码不会执行, <{1}}内的断点未被击中。

2 个答案:

答案 0 :(得分:5)

根据我的理解,ASP有一个指定的线程,它是唯一可以访问graph_data('TSLA') 对象的线程,反过来,访问Session (HttpContext.Current)很像Windows应用程序中的UI线程。因此,在Session_Start回调中执行HttpContext.Current.Session.Wait()会给您带来未知结果和/或使进程死锁。

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

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

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

中正确执行
HttpApplication

答案 1 :(得分:4)

Global.asax中的Session_Start等方法很特殊。你不能随意定义新的。该框架运行其编程运行的框架,并且不提供异步版本。因此,不会运行任何异步版本。

然而,反正异步并不是真的有意义。在启动和关闭App Pool时调用Global.asax方法。因此,在任何时候放弃操作线程都没有意义,因为在完成其工作之前不会发生任何其他事情。

我不完全确定你在做什么,但根据你的代码中的评论,听起来这不是正确的做法。同样,此代码只运行一次,而不是按请求运行。如果您希望每个请求都能发生某些事情,请查看类似操作过滤器的内容。