Domanda

ho alcune cose scritte in C # che esegue il codice concorrente, facendo uso pesante di Task Parallel Library (Task e catene di continuazione Future).

Ora sto porting questo per F # e sto cercando di capire i pro ei contro di utilizzare F # asincrona dei flussi di lavoro contro i costrutti del TPL. Sono appoggiato verso TPL, ma penso che potrebbe essere fatto in entrambi i modi.

Qualcuno ha suggerimenti e la saggezza di scrivere programmi concorrenti in F # da condividere?

È stato utile?

Soluzione

Il nome praticamente riassume la differenza: asincrono vs. programmazione parallelo di programmazione. Ma in F # è possibile combinare.

F # Asynchronous flussi di lavoro

F flussi di lavoro # asincrone sono utili quando si desidera avere il codice eseguito in modo asincrono, che sta iniziando un compito e non aspettare per il risultato finale. L'utilizzo più comune di questo è operazioni di IO. Avere il tuo thread stare lì in un ciclo di inattività in attesa per il disco rigido per finire di scrivere le risorse rifiuti.

Se si è iniziato l'operazione di scrittura in modo asincrono è possibile sospendere il filo e lo hanno svegliato tardi da un interrupt hardware.

Task Parallel libreria

La Biblioteca Task Parallel in .NET 4.0 astrae l'idea di un compito - come la decodifica di un MP3, o la lettura di alcuni risultati da un database. In queste situazioni si vuole realmente il risultato del calcolo e ad un certo punto nel tempo in seguito sono in attesa per il risultato dell'operazione. (Accedendo la proprietà .Result.)

Si può facilmente combinare questi concetti. Come ad esempio fare tutte le operazioni di IO in un oggetto TPL Task. Per il programmatore si è estratta la necessità di 'trattare con' quel filo in più, ma sotto le coperte stai sprecando risorse.

Come saggio è possibile creare una serie di flussi di lavoro F # async ed eseguirli in parallelo (Async.Parallel), ma poi è necessario attendere il risultato finale (Async.RunSynchronously). In questo modo si libera dalla necessità di avviare in modo esplicito tutti i compiti, ma in realtà si sta solo eseguendo il calcolo in parallelo.

Nella mia esperienza trovo che il TPL è più utile, perché di solito io voglio eseguire operazioni in parallelo N. Tuttavia, i flussi di lavoro F # async sono l'ideale quando c'è qualcosa che sta succedendo 'dietro le quinte', come un agente reattivo o il tipo Mailbox cosa. (Si invia qualcosa di un messaggio, lo elabora e lo invia di nuovo).

La speranza che aiuta.

Altri suggerimenti

In 4.0 direi:

  • Se la funzione è sequenziale, utilizzare i flussi di lavoro asincroni. Leggono semplicemente migliore.
  • Utilizza il TPL per tutto il resto.

E 'anche possibile combinare. Hanno aggiunto il supporto per l'esecuzione di un flusso di lavoro come un compito e la creazione di attività che seguono l'async Begin / End modello utilizzando TaskFactory.FromAsync , l'equivalente di TPL 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

E 'anche interessante notare che sia il tempo di esecuzione asincrona Flussi di lavoro e il TPL stanno andando a creare un kernel più primitiva (un evento) e utilizzare WaitForMultipleObjects per tenere traccia di I / O di completamento, piuttosto che utilizzare le porte di completamento e callback. Questo non è auspicabile in alcune applicazioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top