2011-12-12 14 views
6

これはおそらくF#の中で最も基本的なものの1つですが、私は目の前で何が起こっているのか分かりません。スレッドをブロックしないで待機しますか? - どうやって?

let testMe() = 
    async { printfn "before!" 
      do! myAsyncFunction() // Waits without blocking thread 
      printfn "after!" } 

testMe |> Async.RunSynchronously 

do! myAsyncFunction()には何が起こりますか?私は移動する前にmyAsyncFunctionが終了するのを待っていることを知っています。しかし、スレッドをブロックすることなく、どうやってそれを行うことができますか?

私の最高の推測では、myAsyncFunction()の実行が終了した後、同じスレッドmyAsyncFunction()上で実行されます継続が、上で予定されていたとしてdo! myAsyncFunction()後のすべてが渡されるということです..しかし、その後、再び、それはただの推測です。

+1

あなたの推測が正しいと、私は継続がスレッドプール、必ずしも同じスレッドから使​​用可能な次のスレッドで実行されると思いますけれども。 – Daniel

答えて

5

正しく指摘したように、myAsyncFunctionには継続が渡され、完了すると残りの非同期ワークフローが再開されます。

あなたがより良いコードの脱糖バージョンを見て、それを理解することができます

let testMe() = 
    async.Delay(fun() -> 
    printfn "before!" 
    async.Bind(myAsyncFunction(), fun() -> 
     printfn "after!" 
     async.Zero())) 

彼ら重要なのmyAsyncFunctionによって作成された非同期ワークフローがそれを開始し、与えBind操作に与えられていることですワークフローが完了したときに呼び出す関数としての2番目の引数(継続)。あなたは多くのことを簡素化する場合は、非同期ワークフローは次のように定義することができます。

type MyAsync<'T> = (('T -> unit) * (exn -> unit)) -> unit 

ので、非同期ワークフローは、引数として、いくつかの継続を取るだけの機能です。継続が得られると、何か(すなわち、タイマーを作成するかI/Oを開始する)し、最終的にこれらの継続を呼び出す。 「どのスレッドで継続と呼ばれているのですか?興味深いものです。シンプルなモデルでは、起動しているMyAsyncに依存しています。希望の場所(つまり、Async.SwithcToNewThread)で新しいスレッドを実行することができます。 F#ライブラリには、ワークフローを使用したGUIプログラミングを容易にする追加の処理が含まれています。

この例では現在のスレッドをブロックするAsync.RunImmediateを使用していますが、ワークフローを開始するだけのAsync.Startを使用して、生成時にその結果を無視することもできます。 Async.Startの実装は次のようになります。

let Start (async:MyAsync<unit>) = async (ignore, ignore) 
関連する問題