Comme vous l'avez correctement souligné, le myAsyncFunction
est passé une continuation et l'appelle pour reprendre le reste du flux de travail asynchrone lorsqu'il se termine.
Vous pouvez le comprendre mieux en regardant la version Dessucré du code:
let testMe() =
async.Delay(fun() ->
printfn "before!"
async.Bind(myAsyncFunction(), fun() ->
printfn "after!"
async.Zero()))
Ils élément clé est que le flux de travail asynchrone créé par myAsyncFunction
est donnée à l'opération Bind
qui commence et lui donne la second argument (une continuation) en tant que fonction à appeler lorsque le workflow est terminé. Si vous simplifiez beaucoup, alors un flux de travail asynchrone pourrait être défini comme ceci:
type MyAsync<'T> = (('T -> unit) * (exn -> unit)) -> unit
Ainsi, un flux de travail asynchrone est juste une fonction qui prend des continuations comme argument. Quand il obtient les suites, il fait quelque chose (c'est-à-dire crée une minuterie ou démarre des E/S) et ensuite il appelle finalement ces continuations. La question "Sur quel fil sont les continuations appelées?" est intéressant - dans un modèle simple, cela dépend du MyAsync
que vous démarrez - il peut décider de les exécuter où bon lui semble (par exemple Async.SwithcToNewThread
les exécute sur un nouveau thread). La bibliothèque F # inclut des manipulations supplémentaires qui facilitent la programmation de l'interface graphique en utilisant les workflows.
Votre exemple utilise Async.RunImmediate
, qui bloque le thread en cours, mais vous pouvez également utiliser Async.Start
, qui démarre le workflow et ignore le résultat lorsqu'il est généré. La mise en œuvre de Async.Start
pourrait ressembler à ceci:
let Start (async:MyAsync<unit>) = async (ignore, ignore)
Votre supposition est juste, même si je pense que la poursuite sera exécuté sur le prochain fil disponible à partir du pool de threads, pas nécessairement le même fil. – Daniel