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.RunSynchronouslykullanarak 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.AwaitTaskbirleş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 .. elseve if .. then ..gibi for .. in .. dodenetim 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 letuseaynı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.WebExtensionsWeb 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 AsyncDownloadStringlet! yerine letkullanı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()

Ayrıca bkz.