2012-04-26 13 views
28

En C# ¿Hay alguna diferencia entre el uso de un delegado para hacer algún trabajo de forma asíncrona (llamando BeginInvoke()) y el uso de un hilo ThreadPool como se muestra abajoDiferencia entre delegate.BeginInvoke y utilizando hilos ThreadPool en C#

public void asynchronousWork(object num) 
    { 
     //asynchronous work to be done 
     Console.WriteLine(num); 
    } 

public void test() 
    { 
     Action<object> myCustomDelegate = this.asynchronousWork; 
     int x = 7; 

     //Using Delegate 
     myCustomDelegate.BeginInvoke(7, null, null); 

     //Using Threadpool 
     ThreadPool.QueueUserWorkItem(new WaitCallback(asynchronousWork), 7); 
     Thread.Sleep(2000); 
    } 

Editar:
BeginInvoke se asegura de que un subproceso del grupo de subprocesos se utiliza para ejecutar el código asincrónico, por lo que hay alguna diferencia?

+1

posible duplicado de [¿El Func .BeginInvoke utilizar el ThreadPool?] (Http://stackoverflow.com/questions/3556634/does-funct-begininvoke-use-the-threadpool) – nothrow

+0

No estoy seguro de si su comentario fue antes de que editara mi pregunta, pero soy consciente de que BeginInvoke ejecuta delegados en los hilos que pertenecen a la lista de temas. Mi pregunta era más sobre si había alguna diferencia entre ejecutar explícitamente el método en un grupo de subprocesos usando QueueUserWorkItem o al usar BeginInvoke – nighthawk457

Respuesta

31

Joe Duffy, en su Concurrent Programming on Windows libro (página 418), dice lo siguiente acerca Delegate.BeginInvoke:

Todos los tipos de delegado, por la oferta de convenciones y un BeginInvoke EndInvoke método junto con el método ordinario sincrónica Invoke. Si bien esta es una buena característica de modelo de programación, debe mantenerse alejado de ellos siempre que sea posible. La implementación usa una infraestructura remota que impone una sobrecarga considerable a la invocación asincrónica. El trabajo en cola para el grupo de subprocesos directamente es a menudo un mejor enfoque, aunque eso significa que usted tiene que coordinar la lógica de encuentro usted mismo.

EDIT: He creado la siguiente prueba simple de los gastos generales relativos:

int counter = 0; 
int iterations = 1000000; 
Action d =() => { Interlocked.Increment(ref counter); }; 

var stopwatch = new System.Diagnostics.Stopwatch(); 
stopwatch.Start(); 
for (int i = 0; i < iterations; i++) 
{ 
    var asyncResult = d.BeginInvoke(null, null); 
} 

do { } while(counter < iterations); 
stopwatch.Stop(); 

Console.WriteLine("Took {0}ms", stopwatch.ElapsedMilliseconds); 
Console.ReadLine(); 

En mi máquina por encima de las pruebas de funcionamiento en unos 20 segundos. Sustitución de la llamada BeginInvoke con

System.Threading.ThreadPool.QueueUserWorkItem(state => 
{ 
    Interlocked.Increment(ref counter); 
}); 

cambia el tiempo de ejecución de 864ms.

+1

. ¿Siento que viene otra reacción instintiva? Necesitamos algunos datos empíricos para objetivar * una sobrecarga considerable para la invocación asíncrona. * ¿Cuál es la desventaja involucrada al tener * que coordinar la lógica de encuentro usted mismo ... * versus el azúcar sintáctico de las implementaciones asíncronas generalmente aceptadas - p. BeginInvoke, Callback, EndInvoke. Una cosa que obtenemos al utilizar IAsyncResult es un identificador desde el cual podemos monitorear lo que está sucediendo. Nunca he probado nada con ThreadPool para ver si podía hacer lo mismo. – IAbstract

+1

Me pregunto por qué cada delegado define un método 'BeginInvoke' que inicia asíncronamente al delegado. El único aspecto de 'BeginInvoke' que parecería ligado a cualquier firma de delegado en particular sería el proceso de convertir un delegado más parámetros en un elemento unificado, lo que podría haberse hecho igual si cada delegado definió el método' Bind' que tomó el mismos parámetros que el delegado y devolvió un 'MethodInvoker'. – supercat

+1

@IAbstract - Esto es específicamente sobre 'Delegate.Begin \ EndInvoke' no el patrón general' BeginInvoke \ EndInvoke' que se encuentra en el marco. Es cierto que 'IAsyncResult' le da más control, sin embargo, se está abandonando a favor de' Task' en .net 4 y superior. – Lee