Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call Async Method from Session_Start

How can I call an async method from Session_Start in Global.asax ?

Global.asax:

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

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

async method:

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

            await db.SaveChangesAsync();

        }
    }

I can run it all synchronously (define void Session_Start etc.) which is working, but would prefer the async way so that hitting the db is not blocking.

Running like this with 'async Task' for Session_Start, the code is not executed, breakpoints inside session_start are not hit.

like image 464
Danielle Avatar asked Aug 15 '16 13:08

Danielle


People also ask

How do you call async function?

async and await Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.

How do you call async method in controller?

The first thing to do is to add the async keyword to Action Method. If we use the async Keyword in Method, the Method must also use await Keyword. The return type of an async method must be void, Task or Task<T> we have used Task<T> in Action Method.

What happens when you call async method?

The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.


1 Answers

From what I understand, ASP has a designated thread that is the ONLY thread that has access to the HttpContext.Current object, and in turn, access to the Session (HttpContext.Current.Session) much like the UI thread in windows applications. Therefore, performing a .Wait() or .Result in Session_Start callback will give you unknown results and/or deadlock the process.

There seems to be numerous ways to govern a Task's thread of execution, the primary one being specifying your task to run with a certain synchronization context via the TaskScheduler class https://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler(v=vs.110).aspx#Sync

However, since the Task class was designed to implement IAsyncResult, which comes from the APM (Asynchronous Programming Model) pattern, this makes Task backwards compatible with older APM pattern code (Which from what I understand ASP was originally built on). It takes a bit of integration work, though https://blogs.msdn.microsoft.com/mazhou/2011/10/04/the-asynchronous-programming-models/ (Standard APM).

.Net 4.5 introduced a nice Task wrapper (EventHandlerTaskAsyncHelper) to perform asynchronous actions utilizing the APM-style HttpApplication was built to support. It meets all the requirements to access the Session object, and execute correctly in the 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
}
like image 152
AniAko Avatar answered Sep 22 '22 20:09

AniAko