2010-09-14 9 views
5

Actualmente tengo una sección de código que necesita realizar aproximadamente 7 llamadas de servicio web a varios proveedores de datos. Cada llamada tarda unos segundos en ejecutarse, por lo que me gustaría ejecutarlas en paralelo para acelerar las cosas.Usando .Net Parallel Extensions (Parallel.Invoke) para múltiples llamadas asincrónicas?

He envuelto mis 7 llamadas en un Parallel.Invoke la que funciona muy bien en el funcionamiento de un par de cosas al mismo tiempo, pero en un servidor central 2, que sólo ejecutará 2 a la vez, uno por núcleo. Como todo lo que hago es esperar a que regresen las llamadas del servicio web, me gustaría que fuera a buscar las 7 y esperar a que regresen.

¿Hay alguna manera de hacer esto? ¿O tal vez mi enfoque es incorrecto? Tal vez necesito crear llamadas asincrónicas a los servicios web? Pero ¿cómo esperar a que todos regresen antes de seguir?

Respuesta

5

pero en un servidor central 2, sólo se ejecutará 2 a la vez, uno por núcleo

cuestionaría esto - Parallel.Invoke normalmente se ejecutará muchas más tareas que los núcleos en su sistema .

Dicho esto, si utiliza invocaciones de llamada de método asíncrono, le recomendaría usar Task.Factory.FromAsync(...) para generar sus siete tareas distintas.

Esto proporciona la flexibilidad de realizar otro trabajo mientras se ejecutan las tareas, y luego llamar al Task.WaitAll (o Task.WaitAny) cuando decide usar los resultados.

Paralelo.Invocar, por el contrario, siempre se bloqueará hasta que se completen las siete.

+2

Me dio la impresión de que quería que todos los completen antes de continuar. –

+1

@Steven: Lo que puede hacer a través de Task.WaitAll, pero puede hacer otro trabajo mientras espera, si está disponible, si esa es una opción. Sin embargo, casos como este a menudo funcionan con Task.WaitAny, ya que normalmente puede comenzar parte del trabajo tan pronto como se completen algunas de las tareas; es raro que necesite 7 resultados diferentes para realizar cualquier procesamiento ... –

+0

Está bien, esto funcionará también y con más flexibilidad de lo que sugerí. –

0

Puede especificar ParallelOptions para aumentar el nivel de concurrencia. El valor predeterminado es razonable para las tareas vinculadas a la CPU, pero se trata de las vinculadas a E/S, por lo que tiene sentido anular ese comportamiento.

+0

Pensé que aumentar el nivel de concurrencia solo llega a la concurrencia máxima permitida? es decir, si tiene 8 núcleos, puede establecer el nivel de concurrencia a cualquier cosa ... pero ir más allá de 8 no hará nada ... – puffpio

+0

@puffpio: Todo lo que dice es: "El MaxDegreeOfParallelism limita el número de operaciones simultáneas ejecutadas por llamadas a métodos paralelos que pasan esta instancia de ParallelOptions al valor establecido, si es positiva. Si MaxDegreeOfParallelism es -1, entonces no hay límite colocado en el número de operaciones que se ejecutan simultáneamente ". –

+0

Sí, eso me confunde, ya que dice "límite" que para mí significa que no irá más allá de la cantidad de núcleos que tenga. Lo digo porque la página en Parallel.Invoke dice: "Tenga en cuenta que con Invoke(), simplemente debe indicar qué acciones desea ejecutar simultáneamente, y el tiempo de ejecución maneja todos los detalles de programación de subprocesos, incluida la escala automática de la cantidad de núcleos en el el ordenador anfitrión." – puffpio

1

No es necesario utilizar Parallel.Invoke para esto. Puede continuar y emitir las múltiples solicitudes asíncronas (es decir, HttpWebRequest.BeginGetResponse()). En cuanto a recibir una notificación cuando todos se completen, tiene varias opciones. Una manera simple sería inicializar un CountdownEvent antes de emitir la primera solicitud, y luego tener el hilo principal en espera en ese evento después de que se emitan las solicitudes. Los métodos de devolución de llamada asíncrona cada señal ese evento a medida que se completan. De esta forma, se asegura de que todas las solicitudes se hayan completado antes de que su hilo principal continúe.

+1

Pero TPL es mucho más fácil que el APM. Sería bueno si pudiéramos tener lo mejor de ambos mundos. –

+0

Usando Task.Factory.StartAsync brinda lo mejor de ambos mundos ... sin la necesidad de rastrear con CountdownEvent, etc. –

+0

Necesito mirar más de cerca el TPL. –

0

Voy a copiar a response that I made to another question al pie de la letra porque es igual, si no más, aplicable aquí.


Simplemente no se puede superar el modelo de programación asíncrona (APM) cuando se trata de rendimiento de E/S. Cada vez que puedas usarlo, deberías serlo. Afortunadamente, la Task Parallel Library (TPL) viene con soporte para combinar el trabajo de APM en la mezcla con tareas TPL "puras" a través del the FromAsync factory method.

Consulte esta sección del .NET SDK en MSDN titulada TPL and Traditional .NET Asynchronous Programming para obtener más información sobre cómo combinar estos dos modelos de programación para lograr async nirvana.

Cuestiones relacionadas