I'm working on an ASP.NET MVC 4 web application. I'm using .NET 4.5 and am trying to take advantage of the new asynchronous API's.
I have a couple situations where I want to schedule an async Task to run later while I return back an immediately important value right away. For example, here is a "Login" method which I want to return a new SessionID as quickly as possible, but once I've returned the SessionID I want to clean out old expired SessionID's:
public async Task<Guid> LogIn(string UserName, string Password)
{
//Asynchronously get ClientID from DB using UserName and Password
Session NewSession = new Session()
{
ClientID = ClientID,
TimeStamp = DateTime.Now
};
DB.Sessions.Add(NewSession);
await DB.SaveChangesAsync(); //NewSession.ID is autopopulated by DB
CleanSessions(ClientID); //Async method which I want to execute later
return NewSession.ID;
}
private async void CleanSessions(int ClientID)
{
//Asynchronously get expired sessions from DB based on ClientID and mark them for removal
await DB.SaveChangesAsync();
}
I've tried a bunch of different things including combinations of Task.Run() and Parallel.Invoke() but CleanSessions never gets called. How do I achieve background task scheduling?
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.
Async functions don't return immediately, they run the body of the code until the hit an await and return a promise. In your example, the entire function will run before it returns. You can't use this kind of long running process without blocking.
Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.
Running tasks in ASP.NET without a request is not recommended. It's dangerous.
That said, change CleanSessions
to return Task
and you can do it like this:
Task.Run(() => CleanSessions());
In your case, I think it would be OK, because there's no long-term problem if CleanSessions
doesn't execute or gets terminated in the middle of executing (which can happen in ASP.NET due to recycling). If you want to notify ASP.NET that you have some work in progress that is not associated with a request, you can use the BackgroundTaskManager
from my blog like this:
BackgroundTaskManager.Run(() => CleanSessions());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With