2012-06-19 41 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調用。

相關問題