2012-06-19 25 views
10

Tôi cần gọi một số hoạt động không đồng bộ trên DB của mình trong Global.asax. ví dụ trong Application_AuthenticateRequest Tôi cần xác thực người dùng dựa trên DB Có thể thực hiện với các tác vụ không đồng bộ không?ASP.NET: Có thể gọi Công việc không đồng bộ trong Global.asax không?

+0

Tại sao bạn muốn xác thực không đồng bộ? Không nên được thực hiện đồng bộ? – Rich

+1

bởi vì trên nhiều người dùng yêu cầu các cuộc gọi sychronouse đến DB cho người khác yêu cầu phải được xếp vào hàng đợi - nó tăng thời gian phản hồi. xem [Cuộc gọi cơ sở dữ liệu không đồng bộ với mô hình lập trình không đồng bộ dựa trên nhiệm vụ (TAP) trong ASP.NET MVC 4] (http://www.tugberkugurlu.com/archive/asynchronous-database-calls-with-task-based-asynchronous -programming-model-tap-in-asp-net-mvc-4) – user1328761

+2

Chúng tôi quản lý để tăng thông lượng của chúng tôi bằng cách xử lý AuthenticateRequest không đồng bộ. Không cần chuỗi bị chặn bởi mạng. –

Trả lời

2

Tôi không tìm cách sử dụng từ khóa C# mới và không cần chờ đợi, nhưng chúng tôi vẫn có thể sử dụng mẫu APM để sử dụng các hoạt động không đồng bộ trong Global.asax vì nó triển khai giao diện IHttpAsyncHandler. Đây là một mã nhỏ để demo async, ở đây tôi sử dụng một WebRequst làm ví dụ, trong trường hợp của bạn hãy sử dụng hoạt động cơ sở dữ liệu để thay thế.

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

Cảm ơn! Tôi đã tìm thấy :) [http://www.codeproject.com/Articles/373479/Writing-asynchronous-HTTP-Module-in-ASP-NET-4-5](http://www.codeproject. com/Các bài viết/373479/Viết-không đồng bộ-HTTP-Mô-đun-trong-ASP-NET-4-5) – user1328761

1

Bạn phải thêm phiên bản async của AuthenticateRequest. Sử dụng đoạn mã sau:

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

Vấn đề là sau đó, làm thế nào để thực hiện BeginAuthenticateRequestEndAuthenticateRequest sử dụng async mới/đang chờ đợi các tính năng của C#. Đầu tiên, chúng ta hãy phiên bản async của chúng ta về AuthenticateRequest ra khỏi con đường:

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

gì chúng ta cần làm tiếp theo là đưa ra một thực hiện BeginAuthenticateRequest và EndAuthenticateRequest. Tôi đi theo a blog post, nhưng có nguồn gốc thực của riêng tôi:

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

Bạn có thể đọc toàn bộ bài viết liên quan đến xem làm thế nào nó hoạt động, nhưng về cơ bản IAsyncResult được thực hiện bởi công tác, vì vậy tất cả các bạn phải làm là gọi callback khi thực hiện xong .

Các bit cuối cùng là chết dễ dàng:

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

Có một cách dễ dàng hơn để làm điều này bây giờ:

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

Với phương pháp này, bạn định nghĩa một phương pháp sử dụng các từ khóa async và quấn phương pháp mà sử dụng lớp 'EventHandlerTaskAsyncHelper' để tạo các phương thức BeginEventHandler và EndEventHandler để chuyển vào cuộc gọi AddOnAuthenticateRequestAsync.

Các vấn đề liên quan