Eseményalapú aszinkron minta áttekintése
Azok az alkalmazások, amelyek egyszerre sok feladatot hajtanak végre, mégis reagálnak a felhasználói interakciókra, gyakran több szálat használó kialakítást igényelnek. A System.Threading névtér biztosítja a nagy teljesítményű többszálú alkalmazások létrehozásához szükséges összes eszközt, de ezeknek az eszközöknek a hatékony használata jelentős tapasztalatot igényel a többszálú szoftverfejlesztés terén. A viszonylag egyszerű, többszálú alkalmazásokhoz az BackgroundWorker összetevő egyszerű megoldást kínál. Kifinomultabb aszinkron alkalmazásokhoz érdemes lehet olyan osztályt implementálni, amely megfelel az eseményalapú aszinkron mintának.
Az eseményalapú aszinkron minta elérhetővé teszi a többszálú alkalmazások előnyeit, miközben elrejti a többszálas kialakításban rejlő összetett problémákat. Az ezt a mintát támogató osztály használatával a következőket teheti lehetővé:
Időigényes feladatokat hajt végre, például letöltéseket és adatbázis-műveleteket a háttérben, az alkalmazás megszakítása nélkül.
Egyszerre több műveletet hajt végre, és értesítést kap, ha mindegyik befejeződik.
Várjon, amíg az erőforrások elérhetővé válnak az alkalmazás leállítása (blokkolása) nélkül.
Kommunikáljon a függőben lévő aszinkron műveletekkel a jól ismert esemény- és delegálási modell használatával. Az eseménykezelők és a meghatalmazottak használatáról további információt az Események című témakörben talál.
Az eseményalapú aszinkron mintát támogató osztály egy vagy több MetódusnévAsync nevű metódussal rendelkezik. Ezek a metódusok tükrözhetik a szinkron verziókat, amelyek ugyanazt a műveletet hajtják végre az aktuális szálon. Az osztály rendelkezhet MethodName Completed eseménysel is, és lehet, hogy methodNameAsyncCancel (vagy egyszerűen CancelAsync) metódussal rendelkezik.
PictureBox egy tipikus összetevő, amely támogatja az eseményalapú aszinkron mintát. A rendszerképet szinkron módon töltheti le a metódus meghívásával Load , de ha a rendszerkép nagy, vagy ha a hálózati kapcsolat lassú, az alkalmazás a letöltési művelet befejezéséig nem válaszol, és a hívás Load visszatér.
Ha azt szeretné, hogy az alkalmazás továbbra is futjon a kép betöltése közben, meghívhatja a LoadAsync metódust, és kezelheti az LoadCompleted eseményt, ugyanúgy, mint bármely más eseményt. Amikor meghívja a LoadAsync metódust, az alkalmazás továbbra is futni fog, amíg a letöltés egy külön szálon (a háttérben) folytatódik. A rendszer meghívja az eseménykezelőt, amikor a képbetöltési művelet befejeződött, és az eseménykezelő megvizsgálhatja a AsyncCompletedEventArgs paramétert annak megállapításához, hogy a letöltés sikeresen befejeződött-e.
Az eseményalapú aszinkron minta megköveteli az aszinkron művelet megszakítását, és a vezérlő a metódusával támogatja ezt a PictureBox követelményt CancelAsync . A hívás CancelAsync kérést küld a függőben lévő letöltés leállítására, és a feladat megszakítása után az LoadCompleted esemény létrejön.
Figyelemfelhívás
Lehetséges, hogy a letöltés a kéréssel megegyező módon CancelAsync fejeződik be, ezért Cancelled előfordulhat, hogy nem tükrözi a lemondásra vonatkozó kérést. Ezt nevezik versenyfeltételnek, és gyakori probléma a többszálú programozásban. A többszálas programozással kapcsolatos problémákról további információt a Felügyelt szálkezelés ajánlott eljárásai című témakörben talál.
Az eseményalapú aszinkron minta jellemzői
Az eseményalapú aszinkron minta számos formát ölthet az adott osztály által támogatott műveletek összetettségétől függően. A legegyszerűbb osztályok egyetlen MethodNameAsync metódussal és egy megfelelő MethodNameCompleted eseménysel rendelkezhetnek. Az összetettebb osztályok több MethodNameAsync metódussal is rendelkezhetnek, amelyek mindegyike rendelkezik megfelelő MethodNameCompleted eseménysel, valamint ezeknek a metódusoknak a szinkron verzióival. Az osztályok opcionálisan támogathatják a lemondást, a folyamatjelentést és a növekményes eredményeket az egyes aszinkron metódusokhoz.
Az aszinkron metódus több függőben lévő hívást (több egyidejű hívás) is támogathat, így a kód tetszőleges számú alkalommal meghívhatja, mielőtt más függőben lévő műveleteket hajt végre. A helyzet megfelelő kezelése esetén előfordulhat, hogy az alkalmazásnak nyomon kell követnie az egyes műveletek befejezését.
Példák az eseményalapú aszinkron mintára
Az SoundPlayer összetevők az PictureBox eseményalapú aszinkron minta egyszerű implementációit jelölik. Az WebClient összetevők az BackgroundWorker eseményalapú aszinkron minta összetettebb implementációit képviselik.
Az alábbiakban egy példaosztály-deklaráció látható, amely megfelel a mintának:
Public Class AsyncExample
' Synchronous methods.
Public Function Method1(ByVal param As String) As Integer
Public Sub Method2(ByVal param As Double)
' Asynchronous methods.
Overloads Public Sub Method1Async(ByVal param As String)
Overloads Public Sub Method1Async(ByVal param As String, ByVal userState As Object)
Public Event Method1Completed As Method1CompletedEventHandler
Overloads Public Sub Method2Async(ByVal param As Double)
Overloads Public Sub Method2Async(ByVal param As Double, ByVal userState As Object)
Public Event Method2Completed As Method2CompletedEventHandler
Public Sub CancelAsync(ByVal userState As Object)
Public ReadOnly Property IsBusy () As Boolean
' Class implementation not shown.
End Class
public class AsyncExample
{
// Synchronous methods.
public int Method1(string param);
public void Method2(double param);
// Asynchronous methods.
public void Method1Async(string param);
public void Method1Async(string param, object userState);
public event Method1CompletedEventHandler Method1Completed;
public void Method2Async(double param);
public void Method2Async(double param, object userState);
public event Method2CompletedEventHandler Method2Completed;
public void CancelAsync(object userState);
public bool IsBusy { get; }
// Class implementation not shown.
}
A fiktív AsyncExample
osztály két metódussal rendelkezik, amelyek mindegyike támogatja a szinkron és az aszinkron hívásokat. A szinkron túlterhelések bármilyen metódushíváshoz hasonlóan viselkednek, és végrehajtják a műveletet a hívószálon; ha a művelet időigényes, a hívás visszaérkezése jelentős késéssel járhat. Az aszinkron túlterhelések elindítják a műveletet egy másik szálon, majd azonnal visszatérnek, lehetővé téve a hívó szál folytatását, miközben a művelet "a háttérben" fut.
Aszinkron metódus túlterhelései
Az aszinkron műveleteknek két túlterhelése lehet: az egyszeri meghívás és a többszörös meghívás. Ezt a két űrlapot a metódusaik alapján különböztetheti meg: a többszörös meghívású űrlapnak van egy további, úgynevezett paramétere userState
. Ez az űrlap lehetővé teszi, hogy a kód többször is hívjon Method1Async(string param, object userState)
anélkül, hogy várnia kell a függőben lévő aszinkron műveletek befejezésére. Ha viszont egy korábbi hívás befejezése előtt próbál hívást kezdeményezni Method1Async(string param)
, a metódus egy InvalidOperationException.
A userState
többszörös meghívású túlterhelések paramétere lehetővé teszi az aszinkron műveletek megkülönböztetést. Minden egyes híváshoz Method1Async(string param, object userState)
egyedi értéket (például GUID- vagy kivonatkódot) ad meg, és ha minden művelet befejeződött, az eseménykezelő meghatározhatja, hogy a művelet melyik példánya indította el a befejezési eseményt.
Függőben lévő műveletek nyomon követése
Ha a többszörös meghívás túlterheléseit használja, a kódnak nyomon kell követnie a userState
függőben lévő tevékenységek objektumait (feladatazonosítóit). Minden egyes híváshoz Method1Async(string param, object userState)
általában létrehoz egy új, egyedi userState
objektumot, és hozzáadja egy gyűjteményhez. Amikor az objektumnak userState
megfelelő feladat létrehozza a befejezési eseményt, a befejezési módszer implementációja megvizsgálja AsyncCompletedEventArgs.UserState és eltávolítja azt a gyűjteményből. Ezzel a módszerrel a userState
paraméter egy tevékenységazonosító szerepét veszi át.
Feljegyzés
Ügyeljen arra, hogy egyedi értéket userState
adjon a többszörös meghívású túlterhelések hívásaiban. A nem egyedi feladatazonosítók miatt az aszinkron osztály egy ArgumentException.
Függőben lévő műveletek megszakítása
Fontos, hogy a befejezés előtt bármikor le lehessen mondani az aszinkron műveleteket. Az eseményalapú aszinkron mintát megvalósító osztályok rendelkeznek metódussal CancelAsync
(ha csak egy aszinkron metódus van) vagy egy MethodNameAsyncCancel metódussal (ha több aszinkron metódus is létezik).
A több meghívást lehetővé tevő metódusok egy userState
paramétert használnak, amely az egyes tevékenységek élettartamának nyomon követésére használható. CancelAsync
egy paramétert userState
vesz fel, amely lehetővé teszi bizonyos függőben lévő tevékenységek megszakítását.
Azok a metódusok, amelyek egyszerre csak egyetlen függőben lévő műveletet támogatnak, például Method1Async(string param)
, nem törölhetők.
Folyamat Frissítések és növekményes eredmények fogadása
Az eseményalapú aszinkron mintához igazodó osztály opcionálisan eseményt biztosíthat az előrehaladás és a növekményes eredmények nyomon követéséhez. Ez általában el lesz nevezve ProgressChanged
vagy MethodNameProgressChanged, és a megfelelő eseménykezelő egy paramétert ProgressChangedEventArgs fog használni.
Az esemény eseménykezelője ProgressChanged
megvizsgálhatja a ProgressChangedEventArgs.ProgressPercentage tulajdonságot annak megállapításához, hogy egy aszinkron tevékenység hány százaléka lett befejezve. Ez a tulajdonság 0 és 100 közötti lehet, és egy ValueProgressBar. Ha több aszinkron művelet is függőben van, a ProgressChangedEventArgs.UserState tulajdonság segítségével megkülönböztetheti, hogy melyik művelet jelenti az előrehaladást.
Egyes osztályok aszinkron műveletek folytatásaként növekményes eredményeket jelenthetnek. Ezek az eredmények egy olyan osztályban lesznek tárolva, amely származik ProgressChangedEventArgs , és tulajdonságokként jelennek meg a származtatott osztályban. Ezeket az eredményeket az esemény eseménykezelőjében ProgressChanged
érheti el, ugyanúgy, mint a tulajdonságot ProgressPercentage . Ha több aszinkron művelet van függőben, a UserState tulajdonság segítségével megkülönböztetheti, hogy melyik művelet jelent növekményes eredményeket.
Lásd még
- ProgressChangedEventArgs
- BackgroundWorker
- AsyncCompletedEventArgs
- Útmutató: Az eseményalapú aszinkron mintát támogató összetevők használata
- Útmutató: Művelet futtatása a háttérben
- Útmutató: Háttérműveletet használó űrlap implementálása
- Eseményalapú aszinkron minta (EAP)
- Ajánlott eljárások az eseményalapú aszinkron minta implementálására
- Döntés az eseményalapú aszinkron minta implementálásáról
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: