如何从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}}内的断点未被击中。
答案 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方法。因此,在任何时候放弃操作线程都没有意义,因为在完成其工作之前不会发生任何其他事情。
我不完全确定你在做什么,但根据你的代码中的评论,听起来这不是正确的做法。同样,此代码只运行一次,而不是按请求运行。如果您希望每个请求都能发生某些事情,请查看类似操作过滤器的内容。