2010-02-08 15 views
7

que tiene un procesador de buzón de correo que recibe un número fijo de mensajes:fin de Garantía de mensajes enviados al procesador de buzones

let consumeThreeMessages = MailboxProcessor.Start(fun inbox -> 
     async { 
      let! msg1 = inbox.Receive() 
      printfn "msg1: %s" msg1 

      let! msg2 = inbox.Receive() 
      printfn "msg2: %s" msg2 

      let! msg3 = inbox.Receive() 
      printfn "msg3: %s" msg3 
     } 
    ) 

consumeThreeMessages.Post("First message") 
consumeThreeMessages.Post("Second message") 
consumeThreeMessages.Post("Third message") 

Estos mensajes deben ser manejados exactamente en el orden enviada. Durante mis pruebas, imprime exactamente lo que debe:

First message 
Second message 
Third message 

Sin embargo, desde la publicación de mensajes es asincrónico, suena como la publicación de 3 mensajes rápidamente podría dar lugar a artículos que son procesados ​​en cualquier orden. Por ejemplo, yo no desea recibir los mensajes fuera de servicio y obtener algo como esto:

Second message // <-- oh noes! 
First message 
Third message 

son mensajes garantizados a recepción y el tratamiento en el orden enviado? ¿O es posible que los mensajes sean recibidos o procesados ​​fuera de servicio?

+0

Esta es una muy buena pregunta. He estado examinando FSharp.Core.dll pero el código es difícil de entender como C#. – ChaosPandion

Respuesta

8

El código en su función consumeThreeMessages siempre se ejecutará en orden, debido a la forma en que funcionan los flujos de trabajo asincrónicos de F #.

El siguiente código:

async { 
      let! msg1 = inbox.Receive() 
      printfn "msg1: %s" msg1 

      let! msg2 = inbox.Receive() 
      printfn "msg2: %s" msg2 

     } 

se podría traducir como:

async.Bind(
    inbox.Receive(), 
    (fun msg1 -> 
     printfn "msg1: %s" msg1 
     async.Bind(
      inbox.Receive(), 
      (fun msg2 -> printfn "msg2: %s" msg2) 
     ) 
    ) 
) 

Cuando nos fijamos en la forma Desazucarado, está claro que el código se ejecuta en serie. La parte 'async' entra en juego en la implementación de async.Bind, que iniciará el cálculo de forma asíncrona y 'despertará' cuando se complete para finalizar la ejecución. De esta forma, puede aprovechar las operaciones de hardware asíncronas y no perder el tiempo en los subprocesos del sistema operativo que esperan operaciones de E/S.

Sin embargo, eso no significa que no pueda encontrarse con problemas de concurrencia al usar flujos de trabajo asincrónicos de F #. Imagínese que usted hizo lo siguiente:

let total = ref 0 

let doTaskAsync() = 
    async { 
     for i = 0 to 1000 do 
      incr total 
    } |> Async.Start() 

// Start the task twice 
doTaskAsync() 
doTaskAsync() 

El código anterior tendrá dos flujos de trabajo asíncrono modifican el mismo estado al mismo tiempo.

Por lo tanto, para responder a su pregunta en breve: dentro del cuerpo de un solo bloque asíncrono, las cosas siempre se ejecutarán en orden. (Es decir, la siguiente línea después de "¡dejar!" O "¡hacer!" No se ejecuta hasta que se complete la operación asíncrona). Sin embargo, si comparte el estado entre dos tareas asíncronas, entonces todas las apuestas estarán desactivadas. En ese caso, deberá considerar bloquear o usar estructuras de datos concurrentes que vienen con CLR 4.0.

+0

+1, + respuesta: tiene perfecto sentido :) Saben, al principio no estaba 100% seguro porque, solo como experimento, quería implementar procesadores de buzones en C#, y seguí obteniendo resultados no deseados con llamadas secuenciales a mi GetMsg (Acción >) implementación. Mis llamadas anidadas a 'GetMsg (x => GetMsg (y => GetMsg (z => ...>)))' funcionan bien, pero las llamadas secuenciales 'inbox.GetMsg (x => ...); inbox.GetMsg (x =>); inbox.GetMsg (x => ...) 'se procesa fuera de servicio. En lugar de "probablemente haya algo mal con mi código", mi primer pensamiento fue "oye, me pregunto si F # está roto". Afortunadamente no;) – Juliet

+0

Me alegra que tengamos gurús F # en SO. ¿A dónde más recurriríamos? – ChaosPandion

+0

¿Pero se puede reordenar el 'Post's? –

Cuestiones relacionadas