Question

J'ai des choses écrites en C # qui exécute du code concurrent, ce qui rend une utilisation intensive de la bibliothèque parallèle de tâches (tâches et chaînes de continuation futures).

Je suis maintenant le portage à ce F # et essaie de comprendre les avantages et les inconvénients de l'utilisation de F # Async flux de travail par rapport aux constructions du TPL. Je penche vers TPL, mais je pense que cela pourrait se faire de toute façon.

Quelqu'un at-il des conseils et de la sagesse à écrire des programmes concurrents en F # partager?

Était-ce utile?

La solution

Le nom résume assez bien la différence: asynchrone par rapport à la programmation parallèle programmation . Mais en F #, vous pouvez mélanger et assortir.

F # Asynchronous Workflows

F workflows # async sont utiles lorsque vous voulez avoir exécuter du code en mode asynchrone, cela commence une tâche et ne pas attendre que le résultat final. L'usage le plus courant est des opérations d'entrées-sorties. Avoir votre fil assis là dans une boucle d'inactivité en attente de votre disque dur pour terminer gaspille les ressources d'écriture.

Si vous avez commencé l'opération d'écriture de manière asynchrone, vous pouvez suspendre le fil et l'ont pris conscience plus tard par une interruption matérielle.

Bibliothèque parallèle de tâches

La bibliothèque parallèle de tâches dans la version 4.0 .NET fait abstraction de la notion d'une tâche - comme le décodage d'un MP3 ou la lecture des résultats d'une base de données. Dans ces situations, vous voulez vraiment le résultat du calcul et à un moment donné dans le temps plus tard, attendez le résultat de l'opération. (En accédant à la propriété .Result.)

Vous pouvez facilement mélanger et assortir ces concepts. Tels que faire toutes vos opérations d'entrées-sorties dans un objet Tâche TPL. Pour le programmeur, vous avez abstraire la nécessité de « traiter avec » ce fil supplémentaire, mais sous les couvertures vous perdez des ressources.

Comme sage, vous pouvez créer une série de flux de travail F # async et de les exécuter en parallèle (Async.Parallel) mais vous devez attendre le résultat final (Async.RunSynchronously). Cela vous libère de devoir commencer explicitement toutes les tâches, mais vraiment vous en train d'exécuter le calcul en parallèle.

Dans mon expérience, je trouve que le TPL est plus utile parce qu'habituellement je veux exécuter des opérations N en parallèle. Cependant, les flux de travail F # async sont idéales quand il y a quelque chose qui se passe « dans les coulisses », comme un agent réactif ou une chose de type de boîte aux lettres. (Vous envoyez un message quelque chose, il le traite et le renvoie.)

L'espoir qui aide.

Autres conseils

Dans la version 4.0, je dirais:

  • Si votre fonction est séquentielle, utilisez les flux de travail Async. Ils ont tout simplement mieux lire.
  • Utilisez le TPL pour tout le reste.

Il est également possible de mélanger et assortir. Ils ont ajouté le support pour l'exécution d'un flux de travail comme une tâche et la création de tâches qui suivent l'async Begin / motif final à l'aide TaskFactory.FromAsync , l'équivalent de TPL Async.FromBeginEnd ou 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

Il est également intéressant de noter que les deux le moteur d'exécution Async Workflows et le TPL vont créer un noyau primitif supplémentaire (un événement) et utiliser WaitForMultipleObjects pour suivre l'achèvement d'E / S, plutôt que d'utiliser des ports d'achèvement et rappels. Ceci est indésirable dans certaines applications.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top