2011-12-12 21 views
6

Bu muhtemelen F # 'daki en temel şeylerden biridir, fakat fark ettim ki, bu durumun arkasında ne olduğuna dair hiçbir fikrim yok.İş parçacığı engellenmeden bekleyin. - Nasıl?

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

testMe |> Async.RunSynchronously 

Neler oluyor do! myAsyncFunction()? Devam etmeden önce myAsyncFunction'un bitmesini beklediğinin farkındayım. Ama iş parçacığını engellemeden bunu nasıl yapabilir?

En iyi tahminle do! myAsyncFunction() sonra her şey .. myAsyncFunction() çalışmayı tamamlandığında kez myAsyncFunction(), üzerinde planlandı aynı iş parçacığı üzerinde işletilirse devamı olarak birlikte geçti ama sonra tekrar, bu sadece bir tahmin olmasıdır.

+1

Tahminin doğru, ben devam parçacığı havuzu, mutlaka aynı iplikle sonraki uygun iş parçacığı üzerinde işletilecek düşünüyorum rağmen. – Daniel

cevap

5

Doğru şekilde işaret ettiğiniz gibi, myAsyncFunction bir devam ettirilir ve tamamlandığında asenkronize iş akışının geri kalanını devam ettirmek için çağırır.

Sen en iyisi kod şekeri alınmış sürümü bakarak bunu anlayabiliriz:

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

Onlar önemli şey myAsyncFunction yarattığı asenkron iş akışı başlatır ve onu verir Bind operasyonuna verilen olmasıdır iş akışı tamamlandığında çağırılacak bir işlev olarak ikinci argüman (bir devam). Eğer çok basitleştirmek, daha sonra bir zaman uyumsuz iş akışı böyle tanımlanabilir:

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

Yani, zaman uyumsuz bir iş akışı argüman olarak bazı devamlılık alan bir fonksiyon adildir. Süreklilikler geldiğinde, bir şey yapar (yani bir zamanlayıcı yaratır veya I/O'yu başlatır) ve sonunda bu süreklilikleri çağırır. "Hangi iş parçacığı hangi devamda denir?" ilginç bir modeldir - basit bir modelde, başladığınız MyAsync'a bağlıdır - istediği her yerde çalıştırmaya karar verebilir (yani Async.SwithcToNewThread bunları yeni bir iş parçacığında çalıştırır). F # kitaplığı, GUI programlama iş akışlarını kullanarak daha kolay hale getiren bazı ek işlemler içerir.

Örneğiniz, geçerli iş parçacığını engelleyen Async.RunImmediate kullanıyor, ancak iş akışını yeni başlatan ve üretildiğinde sonucu yok sayan Async.Start'u da kullanabilirsiniz. Async.Start uygulanması bu gibi görünebilir:

let Start (async:MyAsync<unit>) = async (ignore, ignore) 
İlgili konular