Aszinkron kifejezések
Ez a cikk az aszinkron kifejezések F#-beli támogatását ismerteti. Az aszinkron kifejezések lehetővé teszik a számítások aszinkron módon történő elvégzését, azaz anélkül, hogy akadályozni lehetne a többi munka végrehajtását. Az aszinkron számítások például olyan alkalmazások írására használhatók, amelyek felhasználói felületekkel rendelkeznek, amelyek az alkalmazás egyéb feladatainak végrehajtásakor is reagálnak a felhasználókra. Az F# aszinkron munkafolyamatok programozási modellje lehetővé teszi funkcionális programok írását, miközben elrejti a száláttűnés részleteit egy tárban.
Az aszinkron kód a .NET-tevékenységeket közvetlenül létrehozó tevékenységkifejezések használatával is létrehozható. A feladatkifejezések használata akkor ajánlott, ha a .NET-feladatokat létrehozó vagy használó .NET-kódtárakkal együttműködik. A legtöbb aszinkron kód F#-ban való írásakor az F# aszinkron kifejezések előnyben részesülnek, mivel tömörebbek, kompozíciósabbak, és elkerülik a .NET-feladatokhoz kapcsolódó bizonyos kifogásokat.
Syntax
async { expression }
Megjegyzések
Az előző szintaxisban az általuk expression
képviselt számítás úgy van beállítva, hogy aszinkron módon fusson, azaz az aktuális számítási szál blokkolása nélkül, amikor aszinkron alvási műveleteket, I/O- és egyéb aszinkron műveleteket hajt végre. Az aszinkron számítások gyakran háttérszálon kezdődnek, miközben a végrehajtás az aktuális szálon folytatódik. A kifejezés Async<'T>
típusa az, ahol 'T
a kulcsszó használatakor a kifejezés return
által visszaadott típus található.
Az Async
osztály számos forgatókönyvet támogató metódusokat biztosít. Az általános megközelítés az, hogy olyan objektumokat hozunk létre Async
, amelyek az aszinkron módon futtatni kívánt számításokat vagy számításokat jelölik, majd ezeket a számításokat az egyik aktiváló függvény használatával indítjuk el. A használt eseményindító attól függ, hogy az aktuális szálat, egy háttérszálat vagy egy .NET-feladatobjektumot szeretne-e használni. Ha például egy aszinkron számítást szeretne elindítani az aktuális szálon, használhatja Async.StartImmediate
a következőt: . Amikor elindít egy aszinkron számítást a felhasználói felületi szálról, nem blokkolja a felhasználói műveleteket, például billentyűleütéseket és egértevékenységeket feldolgozó fő eseményhurkot, így az alkalmazás válaszkész marad.
Aszinkron kötés a Let használatával!
Az aszinkron kifejezésekben egyes kifejezések és műveletek szinkronok, mások pedig aszinkronok. Amikor aszinkron módon hív meg egy metódust, a szokásos let
kötés let!
helyett a . Ennek az a hatása let!
, hogy lehetővé teszi a végrehajtás folytatását más számításokon vagy szálakon a számítás végrehajtása során. Miután a let!
kötés jobb oldala visszatér, az aszinkron kifejezés többi része folytatja a végrehajtást.
Az alábbi kód a kettő és let!
a kettő közötti let
különbséget mutatja be. A kódsor, amely csak let
egy aszinkron számítást hoz létre objektumként, amelyet később futtathat például Async.StartImmediate
vagy Async.RunSynchronously
. A számítást használó let!
kódsor elindítja a számítást, és aszinkron várakozást hajt végre: a szál fel van függesztve, amíg az eredmény el nem érhető, ekkor a végrehajtás folytatódik.
// 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!
csak az F# aszinkron számítások Async<T>
közvetlen várására használható. Más típusú aszinkron műveleteket is várhat közvetetten:
- .NET-feladatok és Task<TResult> nem általánosak Task, a
Async.AwaitTask
- .NET-értékfeladatok és ValueTask<TResult> nem általános ValueTasktevékenységek,
.AsTask()
aAsync.AwaitTask
- Az F# RFC FS-1097-ben megadott "GetAwaiter" mintát követő objektumok a következővel
task { return! expr } |> Async.AwaitTask
kombinálva: .
Átvitelvezérlés
Az aszinkron kifejezések tartalmazhatnak vezérlőfolyamat-szerkezeteket, például for .. in .. do
, while .. do
, try .. with ..
, try .. finally ..
, if .. then .. else
és if .. then ..
. Ezek azonban további aszinkron szerkezeteket is tartalmazhatnak, kivéve azokat a with
kezelőket finally
, amelyek szinkron módon hajtanak végre.
Az F# aszinkron kifejezések nem támogatják az aszinkron try .. finally ..
kifejezést. Ehhez az esethez használhat tevékenységkifejezést.
use
és use!
kötések
Az aszinkron kifejezéseken belül a use
kötések típusértékekhez IDisposableköthetők. Az utóbbi esetében a rendszer aszinkron módon hajtja végre az ártalmatlanítási tisztítási műveletet.
let!
Emellett aszinkron use!
kötéseket is végrehajthat. A különbség let!
use!
és ugyanaz, mint a különbség let
és use
a . Ehhez use!
az objektum az aktuális hatókör végén lesz megsemmisítve. Vegye figyelembe, hogy az F# aktuális kiadásában nem engedélyezi az use!
érték null értékűre való inicializálását, annak ellenére use
, hogy igen.
Aszinkron primitívek
Egy olyan metódust, amely egyetlen aszinkron feladatot hajt végre, és visszaadja az eredményt, aszinkron primitívnek nevezzük, és ezeket kifejezetten a let!
. Az F#-magtárban számos aszinkron primitív definiálva van. A webalkalmazások két ilyen módszere van definiálva a modulban FSharp.Control.WebExtensions
: WebRequest.AsyncGetResponse
és WebClient.AsyncDownloadString
. Mindkét primitív letölt adatokat egy weblapról egy URL-cím alapján. AsyncGetResponse
objektumot System.Net.WebResponse
hoz létre, és AsyncDownloadString
létrehoz egy sztringet, amely egy weblap HTML-jének felel meg.
Az aszinkron I/O-műveletek számos primitív elemét tartalmazza a FSharp.Control.CommonExtensions
modul. Az osztály ezen bővítménymetszetei a System.IO.Stream
következők Stream.AsyncRead
: és Stream.AsyncWrite
.
Saját aszinkron primitíveket is írhat egy függvény vagy metódus definiálásával, amelynek törzse aszinkron kifejezés.
Ha más aszinkron modellekhez tervezett Aszinkron metódusokat szeretne használni az F# aszinkron programozási modellel rendelkező .NET-keretrendszer, létre kell hoznia egy függvényt, amely egy F# Async
objektumot ad vissza. Az F#-kódtár olyan függvényekkel rendelkezik, amelyek megkönnyítik ezt a feladatot.
Az aszinkron kifejezések használatára itt talál egy példát; Az Async osztály módszereinek dokumentációjában sok más is szerepel.
Ez a példa bemutatja, hogyan lehet aszinkron kifejezéseket használni a kód párhuzamos végrehajtásához.
A következő kód példában egy függvény fetchAsync
lekéri egy webes kérelemből visszaadott HTML-szöveget. A fetchAsync
függvény aszinkron kódblokkot tartalmaz. Ha egy aszinkron primitív eredményhez kötést hoz létre, ebben az esetben AsyncDownloadString
a rendszer ahelyett használja a kötést let
. let!
A függvény Async.RunSynchronously
használatával aszinkron műveletet hajthat végre, és megvárhatja az eredményét. Példaként több aszinkron műveletet is végrehajthat párhuzamosan a függvény és a Async.Parallel
Async.RunSynchronously
függvény együttes használatával. A Async.Parallel
függvény felveszi az Async
objektumok listáját, beállítja az egyes Async
tevékenységobjektumok kódot, hogy párhuzamosan fussanak, és visszaad egy Async
objektumot, amely a párhuzamos számítást képviseli. Csakúgy, mint egyetlen művelet esetében, a végrehajtás indítására kell hívnia Async.RunSynchronously
.
A runAll
függvény három aszinkron kifejezést indít el párhuzamosan, és megvárja, amíg az összes befejeződött.
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()
Lásd még
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: