2012-06-19 40 views
10

我需要在Global.asax中对我的数据库调用一些异步操作。 例如在Application_AuthenticateRequest中我需要根据数据库对用户进行身份验证 使用异步任务可能吗?ASP.NET:是否可以在Global.asax中调用异步任务?

+0

为什么你想异步认证?这不应该同步完成吗? – Rich

+1

,因为在许多用户请求对数据库的同步调用后,其他请求者被放入队列 - 这增加了响应时间。请参见[ASP.NET MVC 4中的基于任务的异步编程模型(TAP)中的异步数据库调用](http://www.tugberkugurlu.com/archive/asynchronous-database-calls-with-task-based-asynchronous -programming-model-tap-in-asp-net-mvc-4) – user1328761

+2

我们设法通过异步处理AuthenticateRequest来提高吞吐量。不需要网络阻止线程。 –

回答

2

我没有找到一种方法来使用新的C#关键字异步和等待,但我们仍然可以使用APM模式在Global.asax中使用异步操作,因为它实现了IHttpAsyncHandler接口。这里是一个演示异步的小代码,在这里我使用WebRequst作为例子,请使用数据库操作。

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(); 
    } 
+0

谢谢! 我发现:) [http://www.codeproject.com/Articles/373479/Writing-asynchronous-HTTP-Module-in-ASP-NET-4-5](http://www.codeproject。 COM /文章/ 373479 /写作异步-HTTP-模块式-ASP-NET-4-5) – user1328761

1

您必须自己添加异步版本的AuthenticateRequest。使用下面的代码:

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); 
} 

的问题是,那么,如何使用新的异步实现BeginAuthenticateRequestEndAuthenticateRequest /等待的C#的特征。首先,让我们得到我们AuthenticateRequest的异步版本的出路:

private async Task AuthenticateRequestAsync(object sender, EventArgs args) 
{ 
    // Yay, let's do async stuff! 
    await ... 
} 

我们下一步需要做的就是拿出BeginAuthenticateRequest和EndAuthenticateRequest的实现。我跟着a blog post,但得到的我自己的实现:

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; 
} 

你可以阅读整个链接的文章,看看它是如何工作的,但基本上IAsyncResult通过任务来实现,因此,所有你需要做的是完成时调用回调。

的最后一位是死很容易:

private void EndAuthenticateRequest(IAsyncResult result) 
{ 
    // Nothing to do here. 
} 
18

现在有这样做一个简单的方法:

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(); 
    } 

通过这种方法,您可以定义使用async关键字的方法和换行方法使用'EventHandlerTaskAsyncHelper'类生成BeginEventHandler和EndEventHandler方法以传入AddOnAuthenticateRequestAsync调用。

相关问题