Zaman uyumsuz iş akışları (F#)
Bu konuda, hesaplamaları zaman uyumsuz olarak, diğer bir deyişle, diğer çalışma yürütülmesini engelleme olmadan gerçekleştirmek için F# desteğini açıklar. Örneğin, zaman uyumsuz hesaplamaları, uygulamanın diğer işleri yapar gibi kullanıcılara hızlı tepki veren kalan kullanıcı arabirimleri olan uygulamalar yazmak için kullanılabilir.
async { expression }
Notlar
SD önceki sözdiziminde, temsil ettiği expression zaman uyumsuz olarak, diğer bir deyişle, zaman uyumsuz uyku işlemleri, g/Ç ve diğer zaman uyumsuz işlemler yapılırken geçerli hesaplama iş parçacığı engelleme olmadan çalıştırmak için ayarlayın. Geçerli iş parçacığında yürütme devam ederken zaman uyumsuz hesaplamaları genellikle arka plan iş parçacığı üzerinde başlatıldı. İfade türü Async<'a>, 'a ifade tarafından döndürülen türü, return anahtar sözcüğü kullanılır. Olarak böyle bir ifadeyi kod denir bir zaman uyumsuz blok, veya zaman uyumsuz blok.
Çeşitli şekillerde zaman uyumsuz olarak, programlama vardır ve zaman uyumsuz sınıfı, çeşitli senaryoları desteklemek yöntemleri sağlar. Genel yaklaşım oluşturmaktır Async nesneleri hesaplaması veya zaman uyumsuz olarak çalıştırmak istediğiniz hesaplamaları gösterir ve bu hesaplamaları tetikleyici işlevlerinden birini kullanarak başlatın. Zaman uyumsuz hesaplamaları çalıştıran farklı yoldan çeşitli tetikleyici işlevleri sağlar ve bir kullanın, geçerli iş parçacığı, bir arka plan iş parçacığı kullanmak isteyip istememenize bağlıdır veya bir.net Framework Görev nesnesi ve SD sona erdiğinde çalıştırmalısınız devamı işlevler olsun. Örneğin, geçerli iş parçacığı üzerinde zaman uyumsuz bir hesaplama başlatmak için kullanabileceğiniz Async.StartImmediate. Zaman uyumsuz bir hesaplama UI akıştan başlattığınızda, uygulama tepki kalır, kullanıcı eylemlerini tuş vuruşları ve fare etkinliği gibi işler ana olay döngü engellemeyin.
Let kullanarak zaman uyumsuz bağlama!
Zaman uyumsuz bir iş akışında bazı ifadeler ve işlemleri zaman uyumlu ve zaman uyumsuz bir sonuca dönmek için tasarlanmış uzun hesaplamaları bazılarıdır. Aradığınızda bir yöntem zaman uyumsuz olarak, bir sıradan yerine let bağlamayı kullanmak let!. Etkisini let! SD gerçekleştirildiği gibi diğer hesaplamaları veya iş parçacığı devam etmek yürütme hale getirmektir. Sonra sağ tarafında let! bağlama verir, zaman uyumsuz iş akışı geri kalanı yürütülmesine devam ettirir.
Aşağıdaki kod arasındaki farkı gösterir let ve let!. Kullanan kod satırının let yalnızca zaman uyumsuz bir hesaplama daha sonra kullanarak, örneğin, çalıştırabileceğiniz bir nesne oluşturur Async.StartImmediate veya Async.RunSynchronously. Kullanan kod satırının let! SD başlar ve sonuç hangi noktası yürütülmeye sırasında kullanılabilir olana kadar sonra iş parçacığı askıya alındı.
// let just stores the result as an asynchronous operation.
let (result1 : Async<byte[]>) = stream.AsyncRead(bufferSize)
// let! completes the asynchronous operation and returns the data.
let! (result2 : byte[]) = stream.AsyncRead(bufferSize)
Ek olarak let!, kullanabileceğiniz use! zaman uyumsuz bağlantıları gerçekleştirmek için. Arasındaki fark let! ve use! arasındaki fark ile aynı let ve use. İçin use!, nesne geçerli kapsamı kapanışında kapatılır. F# dili, geçerli sürümde dikkat use! değeri null olarak bile başlatılması izin vermez use yapar.
Zaman uyumsuz ilkel
Tek bir zaman uyumsuz görevi gerçekleştirir ve sonucu döndüren bir yöntem olarak adlandırılan bir zaman uyumsuz temel, bunlar ile kullanılmak üzere özel olarak tasarlanmıştır ve let!. Birden çok zaman uyumsuz ilkel F# Çekirdek Kitaplığı'nda tanımlanır. Bu tür Web uygulamaları için iki yöntem modülünde tanımlanan Microsoft.FSharp.Control.WebExtensions: WebRequest.AsyncGetResponse ve WebClient.AsyncDownloadString. Hem ilkel veri Web url verilen bir sayfasından yükleyin. AsyncGetResponseüreten bir WebResponse nesnesi ve AsyncDownloadString bir Web sayfasının html temsil eden bir dize oluşturur.
Zaman uyumsuz g/Ç işlemleri için birkaç temel öğeler dahil Microsoft.FSharp.Control.CommonExtensions modülü. Bu uzantı yöntemlerini Stream sınıfın Stream.AsyncRead ve Stream.AsyncWrite.
Ek zaman uyumsuz ilkel F# PowerPack içinde kullanılabilir. Tam, gövde zaman uyumsuz bloğunda içine bir işlevi tanımlayarak, kendi zaman uyumsuz ilkel de yazabilirsiniz.
Zaman uyumsuz yöntemleri kullanmak. F# zaman uyumsuz programlama modeli ile zaman uyumsuz diğer modeller için tasarlanmış net Framework F# döndüren bir işlev oluşturun, Async nesne. F# kitaplığı yapın kolaylaştırmak işlevi vardır.
Zaman uyumsuz iş akışları kullanımının bir örneği burada bulunmaktadır; vardır diğer pek çok yöntemlerini belgelerinde zaman uyumsuz sınıf.
Örnek
Bu örnek, zaman uyumsuz iş akışları paralel olarak hesaplamaları gerçekleştirmek için nasıl kullanılacağını gösterir.
Aşağıdaki kod örneği, bir işlev, fetchAsync html metni döndürülen gelen Web isteği alır. fetchAsync İşlevi, zaman uyumsuz bir kod bloğu içeriyor. Ne zaman bağlama yapıldığı zaman uyumsuz bir temel sonucu bu durumda AsyncDownloadString, let! yerine kullanılan let.
İşlevini kullanın Async.RunSynchronously zaman uyumsuz işlemi yürütmek ve sonucu için bekleyin. Örneğin, birden çok zaman uyumsuz işlemlere paralel olarak kullanarak çalıştırabilirsiniz Async.Parallel ile birlikte çalışmaya Async.RunSynchronously işlevi. Async.Parallel İşlev listesini alır Async nesneleri, kodu her biri için ayarlar Async paralel ve döndürür çalıştırılacak Görev nesnesi bir Async Paralel hesaplama temsil eden nesne. Yalnızca tek bir işlem olarak, çağırdığınız Async.RunSynchronously yürütme başlatmak için.
runAll İşlevini üç zaman uyumsuz iş akışları paralel başlatır ve tüm tamamlayıncaya kadar bekler.
open System.Net
open Microsoft.FSharp.Control.WebExtensions
let urlList = [ "Microsoft.com", "https://www.microsoft.com/"
"MSDN", "https://msdn.microsoft.com/"
"Bing", "https://www.bing.com"
]
let fetchAsync(name, url:string) =
async {
try
let uri = new System.Uri(url)
let webClient = new WebClient()
let! html = webClient.AsyncDownloadString(uri)
printfn "Read %d characters for %s" html.Length name
with
| ex -> printfn "%s" (ex.Message);
}
let runAll() =
urlList
|> Seq.map fetchAsync
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
runAll()