I need to call some async operations on my DB in Global.asax. for example in Application_AuthenticateRequest I need to Authenticate user against DB Is it possible with async Tasks?
1 Answer. Show activity on this post. It is best for you to use async/await down the whole call stack which is possible with MVC. Mark your Action as async and then use the await keyword to wait for the results from the CsvReader method.
How can I call a async method on Page_Load ? If you change the method to static async Task instead of void, you can call it by using SendTweetWithSinglePicture("test", "path"). Wait() . Avoid async void unless you are using it for events.
STEP 01 Create new MVC Application project, named as "Async". In the File menu, click New Project. In the "New Project" dialog box, under Project types, expand Visual C#, and then click "Web". In the Name box, type "Async", then click on Ok.
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.
There's an easier way to do this now:
public MvcApplication()
{
var wrapper = new EventHandlerTaskAsyncHelper(DoAsyncWork);
this.AddOnAuthenticateRequestAsync(wrapper.BeginEventHandler, wrapper.EndEventHandler);
}
private async Task DoAsyncWork(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
var ctx = app.Context;
...
await doSomethingAsync();
}
With this approach, you define a method using the async keyword and wrap that method using the 'EventHandlerTaskAsyncHelper' class to generate BeginEventHandler and EndEventHandler methods to pass into the AddOnAuthenticateRequestAsync call.
I didn't find a way to using the new C# keyword async and await, but we can still using APM pattern to use async operations in Global.asax because it implemented IHttpAsyncHandler interface. Here is a small code to demo async, here I use a WebRequst as example, in your case please use database operation instead.
public Global()
{
this.AddOnAuthenticateRequestAsync(BeginGetAsyncData, EndGetAsyncData);
}
IAsyncResult BeginGetAsyncData(Object src, EventArgs args, AsyncCallback cb, Object state)
{
Console.WriteLine("BeginGetAsyncData: thread #" + System.Threading.Thread.CurrentThread.ManagedThreadId);
WebRequest request = WebRequest.Create("http://www.google.com");
return request.BeginGetResponse(cb, request); // call database async operation like SqlCommand.BeginExecuteReader()
}
void EndGetAsyncData(IAsyncResult ar)
{
Console.WriteLine("EndGetAsyncData: thread #" + System.Threading.Thread.CurrentThread.ManagedThreadId);
WebRequest requst = (WebRequest)ar.AsyncState;
System.Net.WebResponse response = requst.EndGetResponse(ar); // call database async operation like SqlCommand.EndExecuteReader()
Console.WriteLine(new StreamReader(response.GetResponseStream()).ReadToEnd());
response.Close();
}
You have to add the async version of the AuthenticateRequest yourself. Using the following code:
public MvcApplication()
{
// Contrary to popular belief, this is called multiple times, one for each 'pipeline' created to handle a request.
// Wire up the async authenticate request handler.
AddOnAuthenticateRequestAsync(BeginAuthenticateRequest, EndAuthenticateRequest, null);
}
The issue is then, how to implement BeginAuthenticateRequest
and EndAuthenticateRequest
using the new async/await features of C#. First, let's get our async version of AuthenticateRequest out of the way:
private async Task AuthenticateRequestAsync(object sender, EventArgs args)
{
// Yay, let's do async stuff!
await ...
}
What we need to do next is come up with an implementation of BeginAuthenticateRequest and EndAuthenticateRequest. I followed a blog post, but derived my own implementation:
private IAsyncResult BeginAuthenticateRequest(object sender, EventArgs args, AsyncCallback callback, object state)
{
Task task = AuthenticateRequestAsync(sender, args);
var tcs = new TaskCompletionSource<bool>(state);
task.ContinueWith(_ =>
{
if (task.IsFaulted && task.Exception != null) tcs.TrySetException(task.Exception.InnerExceptions);
else if (task.IsCanceled) tcs.TrySetCanceled();
else tcs.TrySetResult(true);
if (callback != null) callback(tcs.Task);
}, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default);
return tcs.Task;
}
You can read the entire linked article to see how it works, but basically IAsyncResult
is implemented by Task, so all you have to do is call the callback when done.
The last bit is dead easy:
private void EndAuthenticateRequest(IAsyncResult result)
{
// Nothing to do here.
}
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