Zaman uyumsuz ifadeler
Bu makalede, zaman uyumsuz ifadeler için F# desteği açıklanmaktadır. Zaman uyumsuz ifadeler, diğer işlerin yürütülmesini engellemeden hesaplamaları zaman uyumsuz olarak gerçekleştirmenin bir yolunu sağlar. Örneğin, zaman uyumsuz hesaplamalar, uygulama başka işler gerçekleştirirken kullanıcılara yanıt vermeye devam eden URI'lere sahip uygulamalar yazmak için kullanılabilir. F# Zaman Uyumsuz İş Akışları programlama modeli, bir kitaplık içinde iş parçacığı geçişinin ayrıntılarını gizlerken işlevsel programlar yazmanızı sağlar.
Zaman uyumsuz kod, doğrudan .NET görevleri oluşturan görev ifadeleri kullanılarak da yazılabilir. .NET görevleri oluşturan veya kullanan .NET kitaplıklarıyla birlikte çalışırken görev ifadelerinin kullanılması tercih edilir. F# dilinde en çok zaman uyumsuz kod yazarken, F# zaman uyumsuz ifadeleri daha kısa ve daha kompozisyonlu olduklarından ve .NET görevleriyle ilişkili bazı uyarılardan kaçındıklarından tercih edilir.
Sözdizimi
async { expression }
Açıklamalar
Önceki söz diziminde, tarafından expression
temsil edilen hesaplama zaman uyumsuz olarak, yani zaman uyumsuz uyku işlemleri, G/Ç ve diğer zaman uyumsuz işlemler gerçekleştirildiğinde geçerli hesaplama iş parçacığını engellemeden çalışacak şekilde ayarlanır. Zaman uyumsuz hesaplamalar genellikle geçerli iş parçacığında yürütme devam ederken arka plan iş parçacığında başlatılır. İfadenin türü, Async<'T>
burada 'T
anahtar sözcük kullanıldığında ifade return
tarafından döndürülen türdür.
sınıfı, Async
çeşitli senaryoları destekleyen yöntemler sağlar. Genel yaklaşım, zaman uyumsuz olarak çalıştırmak istediğiniz hesaplamaları veya hesaplamaları temsil eden nesneler oluşturmak Async
ve ardından tetikleyici işlevlerden birini kullanarak bu hesaplamaları başlatmaktır. Kullandığınız tetikleyici, geçerli iş parçacığını mı, arka plan iş parçacığını mı yoksa .NET görev nesnesini mi kullanmak istediğinize bağlıdır. Örneğin, geçerli iş parçacığında zaman uyumsuz bir hesaplama başlatmak için kullanabilirsiniz Async.StartImmediate
. Kullanıcı arabirimi iş parçacığından zaman uyumsuz bir hesaplama başlattığınızda, uygulamanızın yanıt vermeye devam edebilmesi için tuş vuruşları ve fare etkinliği gibi kullanıcı eylemlerini işleyen ana olay döngüsünü engellemezsiniz.
let! kullanarak zaman uyumsuz bağlama
Zaman uyumsuz ifadede, bazı ifadeler ve işlemler zaman uyumlu ve bazıları zaman uyumsuz. Bir yöntemi zaman uyumsuz olarak çağırdığınızda, sıradan let
bir bağlama yerine kullanırsınız let!
. bunun etkisi let!
, hesaplama gerçekleştirilirken yürütmenin diğer hesaplamalarda veya iş parçacıklarında devam edebilmesini sağlamaktır. Bağlamanın sağ tarafı döndürdüğünde let!
, zaman uyumsuz ifadenin geri kalanı yürütmeyi sürdürür.
Aşağıdaki kod ile let!
arasındaki let
farkı gösterir. kullanan let
kod satırı, örneğin veya Async.RunSynchronously
kullanarak Async.StartImmediate
daha sonra çalıştırabileceğiniz bir nesne olarak zaman uyumsuz bir hesaplama oluşturur. Kullanan let!
kod satırı hesaplamayı başlatır ve zaman uyumsuz bir bekleme gerçekleştirir: sonuç kullanılabilir olana kadar iş parçacığı askıya alınır ve bu noktada yürütme devam eder.
// 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)
let!
yalnızca doğrudan F# zaman uyumsuz hesaplamaları Async<T>
beklemek için kullanılabilir. Diğer zaman uyumsuz işlem türlerini dolaylı olarak bekleyebilirsiniz:
- .NET görevleri Task<TResult> ve genel Taskolmayan ile birleştirerek
Async.AwaitTask
- ve ile birleştirerek .NET değer görevleri ve
.AsTask()
genel ValueTaskolmayan görevleri ValueTask<TResult>Async.AwaitTask
- ile
task { return! expr } |> Async.AwaitTask
birleştirilerek F# RFC FS-1097'de belirtilen "GetAwaiter" desenini izleyen herhangi bir nesne.
Denetim Akışı
Zaman uyumsuz ifadeler, , , while .. do
, try .. with ..
try .. finally ..
, if .. then .. else
ve if .. then ..
gibi for .. in .. do
denetim akışı yapılarını içerebilir. Bunlar da zaman uyumlu olarak yürütülen ve finally
işleyicileri dışında with
daha fazla zaman uyumsuz yapı içerebilir.
F# zaman uyumsuz ifadeleri zaman uyumsuz try .. finally ..
'i desteklemez. Bu durum için bir görev ifadesi kullanabilirsiniz.
use
ve use!
bağlamaları
Zaman uyumsuz ifadeler içinde bağlamalar use
türündeki IDisposabledeğerlere bağlanabilir. İkincisi için, atma temizleme işlemi zaman uyumsuz olarak yürütülür.
öğesine ek olarak let!
, zaman uyumsuz bağlamalar gerçekleştirmek için kullanabilirsiniz use!
. ile use!
arasındaki let!
fark ile arasındaki farkla let
use
aynıdır. için use!
nesnesi geçerli kapsamın kapanışında atılır. F# uygulamasının geçerli sürümünde bir use!
değerin null olarak başlatılmasına izin vermediğini unutmayın.use
Zaman Uyumsuz Temel Öğeler
Tek bir zaman uyumsuz görev gerçekleştiren ve sonucu döndüren bir yöntem, zaman uyumsuz ilkel olarak adlandırılır ve bunlar özellikle ile let!
kullanılmak üzere tasarlanmıştır. F# çekirdek kitaplığında birkaç zaman uyumsuz temel öğe tanımlanır. Modülünde FSharp.Control.WebExtensions
Web uygulamaları için bu tür iki yöntem tanımlanır: WebRequest.AsyncGetResponse
ve WebClient.AsyncDownloadString
. Her iki temel öğe de URL'si verilen bir Web sayfasından veri indirir. AsyncGetResponse
bir System.Net.WebResponse
nesnesi oluşturur ve AsyncDownloadString
Bir Web sayfasının HTML'sini temsil eden bir dize oluşturur.
Zaman uyumsuz G/Ç işlemleri için birkaç temel öğe modüle FSharp.Control.CommonExtensions
dahil edilir. sınıfının bu uzantı yöntemleri System.IO.Stream
ve Stream.AsyncWrite
şeklindedirStream.AsyncRead
.
Ayrıca, gövdesi zaman uyumsuz bir ifade olan bir işlev veya yöntem tanımlayarak kendi zaman uyumsuz ilkel öğelerinizi yazabilirsiniz.
.NET Framework'te F# zaman uyumsuz programlama modeliyle diğer zaman uyumsuz modeller için tasarlanmış zaman uyumsuz yöntemler kullanmak için, F# Async
nesnesi döndüren bir işlev oluşturursunuz. F# kitaplığı bunu yapmayı kolaylaştıran işlevlere sahiptir.
Zaman uyumsuz ifadeleri kullanmanın bir örneği burada verilmiştir; Async sınıfının yöntemleri için belgelerde daha birçok başka yöntem vardır.
Bu örnekte, kodu paralel olarak yürütmek için zaman uyumsuz ifadelerin nasıl kullanılacağı gösterilmektedir.
Aşağıdaki kod örneğinde, bir işlev fetchAsync
Web isteğinden döndürülen HTML metnini alır. fetchAsync
işlevi zaman uyumsuz bir kod bloğu içerir. Zaman uyumsuz bir ilkel sonucuna bağlama yapıldığında, bu durumda AsyncDownloadString
let!
yerine let
kullanılır.
zaman uyumsuz bir işlemi yürütmek ve sonucunu beklemek için işlevini Async.RunSynchronously
kullanırsınız. Örneğin, işlevini işleviyle Async.RunSynchronously
birlikte kullanarak Async.Parallel
birden çok zaman uyumsuz işlemi paralel olarak yürütebilirsiniz. Async.Parallel
işlevi nesnelerin listesini alır, her Async
görev nesnesinin Async
kodunu paralel olarak çalışacak şekilde ayarlar ve paralel hesaplamayı temsil eden bir Async
nesne döndürür. Tek bir işlemde olduğu gibi yürütmeyi başlatmak için de çağırırsınız Async.RunSynchronously
.
işlevi paralel runAll
olarak üç zaman uyumsuz ifade başlatır ve hepsi tamamlanana kadar bekler.
open System.Net
open Microsoft.FSharp.Control.WebExtensions
let urlList = [ "Microsoft.com", "http://www.microsoft.com/"
"MSDN", "http://msdn.microsoft.com/"
"Bing", "http://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()