2011-04-19 11 views
6
public void BeforeSendReply(ref Message reply, object correlationState) 
    { 
     var replyCopy = reply; 

     ThreadPool.QueueUserWorkItem(delegate 
     { 
      RequestQueueHandler.RequestQueue.Add((Message)correlationState, replyCopy); 
     }); 
    } 

vsDelegate.BeginInvoke vs ThreadPool.QueueWorkerUserItem

private delegate void RequestQueueHandlerAdd(Message request, Message reply); 

    private static void AsyncMethod(Message request, Message reply) 
    { 
     RequestQueueHandler.RequestQueue.Add(request, reply); 
    } 

    public void BeforeSendReply(ref Message reply, object correlationState) 
    { 
     ((RequestQueueHandlerAdd)AsyncMethod).BeginInvoke((Message)correlationState, reply, null, null); 
    } 

cuál de los dos debería usar? (¿Qué funciona mejor?) ¿por qué?
¿La sobrecarga de mi método influye en la decisión o una de estas implementaciones siempre supera a la otra?
¿por qué?

estoy inclinado hacia ThreadPool.QueueWorkerUserItem pero no tengo ni idea de cuál es realmente mejor, ni en este caso ni en general

ACTUALIZACIÓN

He leído algunas cosas sobre TPL .. trabajado esto fuera:

public void BeforeSendReply(ref Message reply, object correlationState) 
    { 
     var replyCopy = reply; 
     var enqueue = Task.Factory.StartNew(() => RequestQueueHandler.RequestQueue.Add((Message)correlationState, replyCopy)); 

    } 

¿cómo se supone que debo manejar la excepción aquí? Quiero decir, si lo hago

public void BeforeSendReply(ref Message reply, object correlationState) 
    { 
     var replyCopy = reply; 
     var enqueue = Task.Factory.StartNew(() => RequestQueueHandler.RequestQueue.Add((Message) correlationState, replyCopy)); 

     **try 
     { 
      enqueue.Wait(); 
     } 
     catch(AggregateException e) 
     { 
      Handle(e); 
     }** 
    } 

¿No me falta aquí todo el punto de paralelismo?

¿No debería simplemente manejar la posible excepción lanzar en el método RequestQueueHandler.RequestQueue.Add?

+1

¿Qué versión de .NET estás usando? Si está en .NET 4, debe usar la Biblioteca de tareas paralelas. Bueno, no "debería", sino "muy alentado". – Tejs

+0

Estoy usando Framework 4.0, ¿podría ampliarlo, quizás publicarlo como respuesta? – bevacqua

Respuesta

2

Los delegados asíncronos le dan un poco más: valores de retorno y reenvío de excepciones (debe llamar a EndInvoke para obtener acceso a ellos). Al usar ThreadPool directamente, tiene que encargarse de eso usted mismo.

La ventaja de ThreadPool, por otro lado, es la simplicidad.

Eche un vistazo a este excelente en línea book, que analiza los dos (y más) enfoques en profundidad.

Como regla del pulgar:

  • uso TPL si se puede
  • si no uso ThreadPool directamente para fuego simple y olvidar tareas
  • si no uso asíncrono delegados
+0

¿Podría expandir en TPL? Un enlace tal vez? – bevacqua

+0

Claro. El libro anterior tiene un capítulo sobre programación paralela: http://www.albahari.com/threading/part5.aspx, eche un vistazo a la wikipedia también: http://en.wikipedia.org/wiki/Task_Parallel_Library#Task_Parallel_Library – grzeg

+0

La ventaja de QueueWorkerUserItem es que no tiene que esperar la respuesta, BeginInvoke DEBE ser seguido por un EndInvoke eventualmente, de lo contrario, está perdiendo memoria. – Jaap

1

ThreadPool.QueueWorkerUserItem es un nivel superior y preferido. Pero ThreadPool.QueueWorkerUserItem detrás de la escena usa Delegate.BeginInvoke. Pero Delegate.BeginInvoke utiliza hilos del ThreadPool.

3

El método Delegate.BeginInvoke() también usa el ThreadPool, por lo que no espere ninguna diferencia significativa en el rendimiento.

QueueUserWorkItem() no es directamente mejor, simplemente más fácil en la mayoría de los casos.

Pero tenga en cuenta que faltan ambas muestras Manejo de errores.
Su buen delegado corto necesita una try/catch, el escenario BeginInvoke una Devolución de llamada.

Así que cuando puedes usar Fx4 deberías usar el TPL para un nivel de abstracción mucho más alto.

+2

[Esta publicación] (http://shevaspace.blogspot.com/2007/08/delegatebegininvoke-vs.html) revela una diferencia significativa entre BeginInvoke y QueueUserWorkItem. – Gqqnbig

Cuestiones relacionadas