2011-02-18 8 views
5

Estoy implementando una interfaz que requiere implementaciones de los métodos BeginDoSomething y EndDoSomething. Sin embargo, mi DoSomething no es realmente de larga ejecución. Por simplicidad asumen DoSomething sólo compara dos variables y la de regreso si a> bCómo crear un IAsyncResult que se completa inmediatamente?

Así que mi BeginDoSomething debería ser como:

protected override IAsyncResult BeginDoSomething(int a, int b, AsyncCallback callback, object state) 
{ 
    bool returnValue = a > b; 
    return ...; //what should I return here? 
    //The method actually already completed and I don't need to wait for anything 
} 

No sé lo que he de volver. Solo implemento BeginDoSomething porque tengo que hacerlo, no porque mi método sea de larga ejecución. ¿Debo implementar mi propio IAsyncResult? ¿Ya hay una implementación en las bibliotecas .NET?

Respuesta

3

El truco rápida forma de hacerlo es utilizar un delegado:

protected override IAsyncResult BeginDoSomething(int a, int b, AsyncCallback callback, object state) 
{ 
    bool returnValue = a > b; 
    Func<int,int,bool> func = (x,y) => x > y; 
    return func.BeginInvoke(a,b,callback,state); 
} 

La desventaja de este enfoque es tha Debe tener cuidado si dos subprocesos invocarán este método al mismo tiempo y obtendrá un error.

+0

No es realmente rápido, pero es difícil discutir con la simplicidad. Omita returnValue. No veo el error –

+0

¿qué debería estar en el 'EndDoSomething' entonces? Lamento que soy muy nuevo en la programación asincrónica –

+0

en End * sería lo mismo que func.BeginInvoke: IAsyncResult, por lo que de hecho está delegando la responsabilidad a la implementación de Delegate. – Henrik

5

Esto es un poco rápido y sucio, pero se puede implementar una clase que implementa IAsyncResult así:

public class MyAsyncResult : IAsyncResult 
    { 
     bool _result; 

     public MyAsyncResult(bool result) 
     { 
      _result = result; 
     } 

     public bool IsCompleted 
     { 
      get { return true; } 
     } 

     public WaitHandle AsyncWaitHandle 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public object AsyncState 
     { 
      get { return _result; } 
     } 

     public bool CompletedSynchronously 
     { 
      get { return true; } 
     } 
    } 

A continuación, utilizarlo en su BeginDoSomething así:

return new MyAsyncResult(a > b); 
+2

Creo que la propiedad 'AsyncWaitHandle' debería devolver una referencia a * set *' ManualResetEvent' (o similar). Es perfectamente razonable que los clientes intenten esperar en el control, y eso no debería provocar una excepción. – Ani

+0

Cierto, podríamos hacer eso, pero como un WaitHandle es un objeto caro, parece un desperdicio crear uno cuando ** nunca ** sea relevante. –

+2

El código no tiene la llamada de devolución de llamada requerida (si no es nula). –

Cuestiones relacionadas