2009-10-12 8 views
1

Comment puis-je utiliser F #' s support intégré pour les classes d'opérations async exposant la Event-based Asynchronous Pattern tels que classe WebClient?Utilisation F # 's support intégré async avec * méthodes Async()

let Download(url : Uri) = 
    let client = new WebClient() 
    let html = client.DownloadString(url) 
    html 

Lorsque j'essaie de changer cela pour utiliser "let!" dans un async bloc (par exemple tel que décrit au cours des dernières années Soma post)

let Download(url : Uri) = 
    async { 
    let client = new WebClient() 
    let! html = client.DownloadStringAsync(url) 
    return html } 

Je reçois un message d'erreur:

incompatibilité de type de contrainte. L'unité de type est incompatible avec le type Async < 'a> Le type 'unité' est pas compatible avec le type' Async < 'a>'

Edit: Je suis vraiment poser des questions sur la question générale de l'utilisation * Async() méthodes, WebClient est juste un exemple facile. Microsoft says "... vous devriez exposer des fonctionnalités asynchrones en utilisant le modèle asynchrone basé sur les événements [par opposition à BeginFoo()/EndFoo()] chaque fois que possible ..." donc je pense qu'il devrait y avoir un moyen facile de consommer arbitrairement * Async() méthode de F #.

Répondre

5

La méthode WebClient.DownloadStringAsync fait partie du framework .NET. Il va déclencher un événement pour signaler sa progression, et son type de retour est unit, donc vous ne voulez pas l'utiliser, et il n'y a aucun avantage à l'encapsuler dans un objet async.

Le F # PowerPack définit une méthode d'extension, val webclient.AsyncDownloadString : uri -> Async{string}:

let Download(url : Uri) = 
    async { 
    let client = new WebClient() 
    client.Encoding <- Encoding.GetEncoding("utf-8") 
    let! html = client.AsyncDownloadString(url) 
    return html } 

Malheureusement, le choix des conflits de noms avec la méthode webclient existante, ce qui peut causer de la confusion compréhensible. Cependant, je crois que toutes les extensions asynchrones F # commencent par Async*.


[Modifier pour ajouter en réponse aux commentaires:]

Habituellement, .NET utilise le modèle BeginFoo/de EndFoo pour la concurrence. Si les types sont corrects, vous pouvez simplement utiliser Async.BuildPrimitive beginMethod endMethod, ce qui renvoie un wrapper asynchrone pour la méthode.

Parfois, les objets n'utilisent pas ce modèle, comme WebClient, et vous devez utiliser Async.AwaitEvent pour attendre le déclenchement d'un événement ou écrire votre propre boucle pour vérifier à plusieurs reprises si un booléen est défini. Voici un joli article on converting events to Async objects. Pour ce que ça vaut, si vous avez F # installé, vous devriez aussi avoir le code source qui vous donnera une idée de la façon dont l'équipe F # implémente ses extensions asynchrones. Sur ma machine, le fichier correspondant est situé à:

C:\Program Files\FSharp-1.9.6.16\source\fsppack\FSharp.PowerPack\AsyncOperations.fs 
+1

Alors comment ce problème - en utilisant une méthode * Async() - serait-il traité en général? Est-ce que je dois écrire une méthode d'extension F # à chaque fois? –

+0

Plus maintenant: http://msdn.microsoft.com/fr-fr/library/ms228966.aspx "... vous devez exposer des fonctions asynchrones en utilisant le modèle asynchrone basé sur les événements autant que possible ..." –

Questions connexes