2010-05-05 14 views
8

Para evitar la congelación de GUI, quería ejecutar el método conectando a DB asincrónicamente. Por lo tanto, he escrito esto:¿Por qué mi método BeginInvoke no es asincrónico?

DelegatLoginu dl = ConnectDB; 

IAsyncResult ar = dl.BeginInvoke(null, null); 

var result = (bool)dl.EndInvoke(ar); 

Pero todavía está helando y no entiendo por qué. Pensé que BeginInvoke garantiza que el código invocado se ejecuta en otro hilo. ¡Gracias!

Respuesta

12

Llamar a EndInvoke() se bloqueará hasta que se complete la llamada a BeginInvoke().

necesita este tipo de patrón para que su método de larga duración para invocar una devolución de llamada cuando termina:

public void DemoCallback() 
{ 
    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ; 
    string s ; 
    int iExecThread; 

    // Create the callback delegate. 
    AsyncCallback cb = new AsyncCallback(MyAsyncCallback); 

    // Initiate the Asynchronous call passing in the callback delegate 
    // and the delegate object used to initiate the call. 
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, cb, dlgt); 
} 

public void MyAsyncCallback(IAsyncResult ar) 
{ 
    string s ; 
    int iExecThread ; 

    // Because you passed your original delegate in the asyncState parameter 
    // of the Begin call, you can get it back here to complete the call. 
    MethodDelegate dlgt = (MethodDelegate) ar.AsyncState; 

    // Complete the call. 
    s = dlgt.EndInvoke (out iExecThread, ar) ; 

    MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\", 
           and the number {1}", s, iExecThread.ToString())); 
} 
+0

¿Tengo que utilizar la clase AsyncCallBack o puedo pasar un delegado simple? – Petr

+1

Tiene que ser un delegado AsyncCallBack, es decir,su función debe verse como el ejemplo de MyAsyncCallback() anterior - return void, y tomar IAsyncResult como parámetro. – RickL

+0

He probado este código localmente y no funciona (compila, pero no muestra nada en la pantalla): http://ideone.com/V8b2NY – InfZero

2

Está bloqueando inmediatamente su subproceso de interfaz de usuario al llamar al dl.EndInvoke(ar). Este tipo de derrotas el propósito de tener una llamada asincrónica.

+0

Bueno, era mz supongo ... ¿para qué sirve esto? Pensé que hace todo lo relacionado con la conexión en el entorno y luego solo devuelve :( – Petr

+0

El 'BeginXxx' regresa justo después de la llamada, en ese punto las cosas de la conexión se manejan en segundo plano. Cuando el resultado esté listo, obtendrá notificada (ya sea por una devolución de llamada o por sondeo en 'WaitHandle' en' IAsyncResult' devuelto por la llamada 'BeginXxx'). En este punto, usted invoca el' EndXxx' para recuperar el resultado (u obtiene excepciones que ocurrieron en la llamada). Llamar 'EndXxx' temprano obliga a esperar hasta que el resultado esté listo. – Lucero

5

Ver la descripción de EndInvokehere, específicamente:

El EndInvoke() la función se usa para recuperar los resultados de la llamada asincrónica . Se puede llamar en cualquier momento después de BeginInvoke(). Si la llamada asincrónica aún no ha completado , EndInvoke() bloquea hasta que se complete .

0

Especifique un método que se invocará cuando la llamada se complete en BeginInvoke (como dl.BeginInvoke (null, OnConnectCompleted)). Entonces el hilo no será bloqueado.

0

Llamar a EndInvoke bloqueará el hilo actual. Debería pasar un delegado al BeginInvoke en lugar de llamar al EndInvoke

1

Hay 4 patrones diferentes para usar el modelo asincrónico en .NET as this question, cubre muy bien.

Estás utilizando el "Te llamaré" acercamiento. Sin embargo, si desea esperar hasta que el elemento de trabajo ha terminado, la mejor técnica es usar un Mutex (el WaitHandle):

void Run() 
{ 
    Action<string> doWork = DoWork; 
    IAsyncResult result = doWork.BeginInvoke("I will call you", null, null); 

    // You "call the method" - wait 10 seconds for the method to finish. 
    bool success = result.AsyncWaitHandle.WaitOne(10 * 1000); 
} 

void DoWork() 
{ 
} 

Sospecho que no desea bloquear, en cuyo caso "fuego y olvide " causa menos dolores de cabeza.

Cuestiones relacionadas