Pregunta

Tengo algunas cosas escritas en C # que ejecuta el código concurrente, lo que hace un uso intensivo de la tarea paralela Biblioteca (tareas y cadenas de continuación futuros).

Ahora estoy portar este a F # y estoy tratando de averiguar los pros y los contras del uso de F # asíncrono flujos de trabajo frente a las construcciones en el TPL. Me estoy inclinando hacia TPL, pero creo que se podría hacer de cualquier manera.

¿Alguien tiene consejos y sabiduría acerca de la escritura de programas concurrentes en Fa # para compartir?

¿Fue útil?

Solución

El nombre resume bastante bien la diferencia: asíncrono frente a la programación paralelo programación. Pero en F # se puede mezclar y combinar.

F # asíncrono flujos de trabajo

F # flujos de trabajo asincrónicos son útiles cuando se desea tener código de ejecutar de forma asincrónica, que está empezando una tarea y no esperar a que el resultado final. El uso más común de esto es las operaciones de IO. Tener su hilo se sienta allí en un bucle inactivo a la espera de su disco duro para terminar de escribir un desperdicio de recursos.

Si comenzó la operación de escritura asíncrona se puede suspender el hilo y lo han despertado más tarde por una alarma de proceso.

tarea paralela Biblioteca

La biblioteca de tareas en paralelo .NET 4.0 abstrae la noción de una tarea - tales como la decodificación de un MP3, o la lectura de algunos resultados de una base de datos. En estas situaciones que realmente desea que el resultado del cálculo y en algún momento en el tiempo más adelante está esperando el resultado de la operación. (Al acceder a la propiedad .Result.)

Usted puede mezclar fácilmente y combinar estos conceptos. Tales como hacer todas sus operaciones de IO en un objeto de TPL de tareas. Para el programador que ha abstraído la necesidad de 'acuerdo con' ese hilo extra, pero bajo las sábanas que está perdiendo recursos.

Como sabio puede crear una serie de flujos de trabajo de F # asincrónicos y ejecutarlos en paralelo (Async.Parallel) pero entonces es necesario esperar a que el resultado final (Async.RunSynchronously). Esto le libera de tener que iniciar explícitamente todas las tareas, pero en realidad sólo están realizando el cálculo en paralelo.

En mi experiencia he encontrado que el TPL es más útil porque por lo general quiero ejecutar N operaciones en paralelo. Sin embargo, los flujos de trabajo F # asincrónicos son ideales cuando hay algo que está pasando 'entre bastidores', tales como un agente reactivo o escribe el buzón cosa. (Se envía un mensaje algo, lo procesa y lo envía de vuelta.)

Espero que ayude.

Otros consejos

4.0, diría:

  • Si su función es secuencial, utilizar los flujos de trabajo asincrónicos. Ellos simplemente leen mejor.
  • Utilice el TPL para todo lo demás.

También es posible mezclar y combinar. Se ha añadido soporte para ejecutar un flujo de trabajo como una tarea y la creación de las tareas que siguen los asíncrono Begin / End patrón usando TaskFactory.FromAsync , el equivalente TPL de Async.FromBeginEnd o Async.BuildPrimitive.

let func() =
    let file = File.OpenRead("foo")
    let buffer = Array.zeroCreate 1024
    let task1 = Task.Factory.FromAsync(file.BeginRead(buffer, 0, buffer.Length, null, null), file.EndRead)
    task1.Start()

    let task2 = Async.StartAsTask(file.AsyncRead(1024))
    printfn "%d" task2.Result.Length

Es también digno de mención que tanto el tiempo de ejecución asíncrono flujos de trabajo y el TPL van a crear un núcleo adicional primitiva (un evento) y el uso de WaitForMultipleObjects para realizar un seguimiento de I / O finalización, en lugar de utilizar los puertos de finalización y devoluciones de llamada. Esto no es deseable en algunas aplicaciones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top