2012-06-19 13 views
10

Necesito llamar a algunas operaciones asíncronas en mi base de datos en Global.asax. por ejemplo en Application_AuthenticateRequest Necesito autenticar usuario contra DB ¿Es posible con tareas asincrónicas?ASP.NET: ¿Es posible llamar a la tarea asincrónica en Global.asax?

+0

¿Por qué quiere autenticarse de forma asíncrona? ¿No debería hacerse eso sincrónicamente? – Rich

+1

porque en muchas solicitudes de usuario, sychronouse llama a DB para que otros requers se coloquen en la cola, esto aumenta el tiempo de respuesta. consulte [Llamadas asíncronas de base de datos con el modelo de programación asíncrono basado en tareas (TAP) en ASP.NET MVC 4] (http://www.tugberkugurlu.com/archive/asynchronous-database-calls-with-task-based-asynchronous -programación-modelo-tap-en-asp-net-mvc-4) – user1328761

+2

Hemos logrado aumentar nuestro rendimiento manejando AuthenticateRequest de forma asíncrona. No es necesario que el hilo sea bloqueado por la red. –

Respuesta

2

No encontré la manera de utilizar la nueva palabra clave C# async y espero, pero aún podemos usar el patrón APM para usar operaciones asincrónicas en Global.asax porque implementó la interfaz IHttpAsyncHandler. Aquí hay un pequeño código para demostración asíncrona, aquí utilizo un WebRequst como ejemplo, en su caso use la operación de la base de datos.

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

¡Gracias! He encontrado :) [http://www.codeproject.com/Articles/373479/Writing-asynchronous-HTTP-Module-in-ASP-NET-4-5](http://www.codeproject. com/Articles/373479/Writing-asynchronous-HTTP-Module-in-ASP-NET-4-5) – user1328761

1

Tiene que agregar la versión asincrona de AuthenticateRequest. Usando el siguiente código:

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

La cuestión es entonces, cómo implementar y BeginAuthenticateRequestEndAuthenticateRequest utilizando el nuevo asíncrono/espera de características de C#. En primer lugar, vamos a obtener nuestra versión asíncrona de AuthenticateRequest fuera del camino:

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

Lo que tenemos que hacer ahora es llegar a una implementación de BeginAuthenticateRequest y EndAuthenticateRequest. Seguí a blog post, embargo, a partir de mi propia aplicación:

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

Usted puede leer todo el artículo enlazado para ver cómo funciona, pero básicamente IAsyncResult es implementado por el Grupo, así que todo lo que tiene que hacer es llamar a la devolución de llamada cuando se hace .

La última parte es fácil de muertos:

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

Hay una manera más fácil de hacer esto ahora:

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

Con este enfoque, se define un método que utiliza la palabra clave asíncrono y envolver ese método utilizando la clase 'EventHandlerTaskAsyncHelper' para generar los métodos BeginEventHandler y EndEventHandler para pasar a la llamada AddOnAuthenticateRequestAsync.

Cuestiones relacionadas