Zaman uyumsuz ve görev işlevleri

FSharp.Core 11 görev birlikte çalışma, sonuç dönüştürmeleri ve sınırlanmış eşzamanlılık için işlevler ekler. Bunları mevcut zaman uyumsuz iş akışları ve görev ifadeleriyle kullanın; çalışma zamanı zaman uyumsuz prototipi gerektirmez.

Zaman uyumsuz .NET işlemleri bekle

Zaman uyumsuz iş akışının iptal belirteciyle bir .NET işlemi başlatmak için bir fabrikayı öğesine Async.StartTaskImmediategeçirin:

open System.IO

let tryReadFile path =
    async {
        try
            let! contents =
                Async.StartTaskImmediate(fun ct -> File.ReadAllTextAsync(path, ct))
            return Some contents
        with :? FileNotFoundException ->
            return None
    }

Okunan dosya iş akışının iptal belirtecini alır. Eksik bir dosya döndürür None; başarılı bir okuma döndürür Some contents. İş akışı, iptal ve temizleme de dahil olmak üzere tamamlanmasını bekler.

Zaten görev benzeri bir değeriniz varsa kullanın Async.Await . Her iki API de hatalı bir görevin temel alınan tek özel durumunu doğrudan yayılım. Birden çok iç özel durum içeren bir toplama, toplama olarak kalır. Async.AwaitTask mevcut özel durum sarmalama davranışını korur.

API Desteklenen bağımsız değişken/sonuç şekilleri
Async.Await Task<'T> -> Async<'T>; Task -> Async<unit>
Async.Await ValueTask<'T> -> Async<'T>; ValueTask -> Async<unit>
Async.Await Protokolü kullanarak GetAwaiter satır içi görev benzeri aşırı yükleme.
Async.StartTaskImmediate (CancellationToken -> Task<'T>) -> Async<'T>; genel Task olmayan döndürür Async<unit>.
Async.StartTaskImmediate Karşılık gelen ValueTask, ValueTask<'T>ve görev benzeri fabrika aşırı yüklemeleri.
Task.startAsyncImmediate CancellationToken -> Async<'T> -> Task<'T>
Async.RunSynchronouslyImmediate Async<'T> * ?cancellationToken: CancellationToken -> 'T

Async.RunSynchronouslyImmediate ön plan iş parçacığından farklı olarak Async.RunSynchronously çağıran iş parçacığında başlar ve tamamlanması için bloklar. Zaman aşımı parametresi yok. Kullanıcı arabiriminde ve istek iş parçacıklarında zaman uyumsuz bileşimi tercih edin.

Zaman uyumsuz iş akışını görev olarak kullanıma sunma

Yukarıdaki dosya okuma iş akışını görev tabanlı arayanlara sunmak için iptal belirtecini kabul edin ve üzerinden geçirin Task.startAsyncImmediate:

let tryReadFileTask (path: string) (ct: CancellationToken) =
    tryReadFile path |> Task.startAsyncImmediate ct

Köprü geri döner Task<string option> ve iptali yayılır. İlk askıya alma tarihine kadar çağrı iş parçacığında başlar; daha sonra devam edenlerin bu iş parçacığını kullanmaması gerekir.

Bağlı eşzamanlılık

Bir Async<'T> değer ertelenen çalışmayı açıklar. Görev genellikle zaten başlamış bir işlemi temsil eder. Kaynak kullanımını sınırlamak için, görev çalışmasını zaten çalışan görevler yerine fabrikalar olarak tanımlayın:

open System.IO
open System.Threading

let readFiles (paths: seq<string>) (ct: CancellationToken) =
    paths
    |> Seq.map (fun path ->
        fun token -> File.ReadAllTextAsync(path, token))
    |> Task.parallelLimit 4 ct

Task.parallelLimit en fazla hesaplamaların pozitif sınırını eşzamanlı olarak başlatır ve sonuçları giriş sırasına göre döndürür. Başlangıç sırası ve tamamlanma sırası aksi takdirde belirtilmez. Birden fazla eşzamanlılık için, her fabrika eşdüzey hataya işaret eden bağlantılı bir belirteç alır; sıralı yürütme için sağlanan belirteci doğrudan alır.

Bir hesaplama hatası olduğunda, eşdüzeyleri için iptal istenir. İşlemler işbirliği yapmak için belirteçlerini gözlemlemelidir. Birkaç hesaplama başarısız olursa, bir özel durum yayılır; hangi hatanın kazanıldığına bağlı değildir.

Function İmza şekli
Task.parallelLimit int -> CancellationToken -> seq<CancellationToken -> Task<'T>> -> Task<'T[]>
Task.parallelDoLimit int -> CancellationToken -> seq<CancellationToken -> Task<unit>> -> Task<unit>
Task.sequential CancellationToken -> seq<CancellationToken -> Task<'T>> -> Task<'T[]>
Task.sequentialDo CancellationToken -> seq<CancellationToken -> Task<unit>> -> Task<unit>
Async.parallelLimit int -> seq<Async<'T>> -> Async<'T[]>
Async.parallelDoLimit int -> seq<Async<unit>> -> Async<unit>
Async.sequentialDo seq<Async<unit>> -> Async<unit>

İşlevler Async iş akışının ortam iptal belirtecini akıtır. Mevcut Async.Parallel (eşzamanlılık sınırı seçeneği dahil) ve Async.Sequential kullanılabilir durumda kalır. Yalnızca Do tamamlamanız gerektiğinde çeşitlemeler bir unit sonuç sunar. Eşzamanlılık sınırı hız sınırlayıcısı değildir: Hızlı işlemler yine de saniyede çok sayıda istek üretebilir.

Sonuçları dönüştürme ve hatalardan kurtarma

Microsoft.FSharp.Control.Async, Taskve ValueTask modülleri bu nitelikli işlevleri kullanıma sunar. M<'T> şekil sütununda F# türü kısaltması değil, karşılık gelen hesaplama türü anlamına gelir.

Nitelenmiş işlevler Shape
Async.result, Task.result, ValueTask.result 'T -> M<'T>
Async.map, Task.map, ValueTask.map ('T -> 'U) -> M<'T> -> M<'U>
Async.bind, Task.bind, ValueTask.bind ('T -> M<'U>) -> M<'T> -> M<'U>
Async.ignore<'T>, Task.ignore<'T>, ValueTask.ignore<'T> M<'T> -> M<unit>; açık giriş türü bağımsız değişkeni gereklidir.
Async.catchWith, Task.catchWith, ValueTask.catchWith (exn -> 'T) -> M<'T> -> M<'T>
Async.catch, Task.catch, ValueTask.catch M<'T> -> M<Result<'T, exn>>
Async.empty, Task.empty, ValueTask.empty M<unit>
Task.ofValueTask ValueTask<'T> -> Task<'T>
ValueTask.ofTask Task<'T> -> ValueTask<'T>

Örneğin, bir dosyanın içeriğini bir uzunluğa eşleyin ve ardından bir okuma hatasını olarak Resulttemsil edin:

open System.IO
open System.Threading

let fileLength (path: string) (ct: CancellationToken) =
    File.ReadAllTextAsync(path, ct)
    |> Task.map String.length
    |> Task.catch

içeren Report 1 bir dosya verir Ok 8. Eksik bir dosya içeren bir ErrorFileNotFoundExceptionverir. Başarılı bir değeri dönüştürmek yerine atmak için çağırdığınızda ignoregiriş türünü belirtin:

let completion: System.Threading.Tasks.Task<unit> =
    Task.result 42 |> Task.ignore<int>

catchWith iptal edilmeyen bir hata için değiştirme değeri sağlar; başka bir zaman uyumsuz hesaplama çalıştırmaz. catchveya ErrordöndürürOk. İptal işlemi bir hata değerine dönüştürülemez veya kurtarma işleyicisine geçirilmiyor. Task.empty, genel Task.CompletedTaskolmayan bir Task<unit>değildir.

Küçük harflerden Async.catchfarklı olarak, var olan Async.Catch döndürür Choice. Kurtarma, çağrıdan önce oluşan zaman uyumlu özel durumları değil, sağlanan hesaplama hatalarını işler. Zaman uyumsuzluk ertelenmiş olarak kalır; görevler istekli olmaya devam ediyor.

ValueTask ve kitaplık kullanılabilirliği

ValueTask API'leri, FSharp.Core 11'in veya net10.0 derlemesini gerektirirnetstandard2.1. Bkz . Çekirdek hedef seçimi.

ValueTask tek tüketim sözleşmesini inceleyin: her değeri ayrı beklemeler veya işlem hatları aracılığıyla değil bir kez kullanın. Yinelenen beklemeler için bir kez çağırın Task.ofValueTask ve yalnızca sonuçta elde edilen görevi yeniden kullanın.

Ayrıca bkz.