Az eseményalapú aszinkron minta implementálása
Ha olyan osztályt ír, amely néhány olyan művelettel rendelkezik, amely jelentős késéseket okozhat, fontolja meg az aszinkron funkciók megadását az eseményalapú aszinkron minta implementálásával.
Az eseményalapú aszinkron minta szabványosított módot biztosít az aszinkron funkciókkal rendelkező osztályok csomagolására. Ha olyan segédosztályokkal van implementálva, mint például AsyncOperationManager, az osztály minden alkalmazásmodellben megfelelően fog működni, beleértve a ASP.NET, a konzolalkalmazásokat és a Windows Forms-alkalmazásokat.
Az eseményalapú aszinkron mintát megvalósító példa: Útmutató: Az eseményalapú aszinkron mintát támogató összetevő implementálása.
Az egyszerű aszinkron műveletekhez megfelelőnek találhatja az összetevőt BackgroundWorker . További információBackgroundWorker: Művelet futtatása a háttérben.
Az alábbi lista a jelen témakörben tárgyalt eseményalapú aszinkron minta funkcióit ismerteti.
Az eseményalapú aszinkron minta implementálásának lehetőségei
Aszinkron metódusok elnevezése
Opcionálisan a lemondás támogatása
Opcionálisan az IsBusy tulajdonság támogatása
Opcionálisan támogatás biztosítása a folyamatjelentéshez
Igény szerint támogatás megadása növekményes eredmények visszaadására
Out and Ref Parameters in Methods (Out and Ref Parameters in Methods) kezelése
Az eseményalapú aszinkron minta implementálásának lehetőségei
Fontolja meg az eseményalapú aszinkron minta implementálását, ha:
Az osztály ügyfeleinek nincs szükségük WaitHandle az IAsyncResult aszinkron műveletekhez elérhető objektumokra, ami azt jelenti, hogy a lekérdezést WaitAll az ügyfélnek kell létrehoznia, vagy WaitAny létre kell állítania.
Azt szeretné, hogy az aszinkron műveleteket az ügyfél felügyelje a jól ismert esemény-/delegálási modellel.
Minden művelet az aszinkron implementáció egyik jelöltje, de figyelembe kell venni azokat, amelyek hosszú késéssel járnak. Különösen megfelelőek azok a műveletek, amelyekben az ügyfelek metódust hívnak meg, és a befejezéskor értesítést kapnak, további beavatkozás nélkül. Megfelelőek azok a műveletek is, amelyek folyamatosan futnak, és rendszeres időközönként értesítik az ügyfeleket az előrehaladásról, a növekményes eredményekről vagy az állapotváltozásokról.
Az eseményalapú aszinkron minta támogatásának időpontjáról további információt az eseményalapú aszinkron minta implementálásának időpontjáról szóló témakörben talál.
Aszinkron metódusok elnevezése
Minden olyan szinkron metódushoz, amelyhez aszinkron megfelelőt szeretne megadni:
Adjon meg egy MethodNameAsync metódust, amely:
A visszaadott érték.
void
Ugyanazokat a paramétereket veszi fel, mint a MethodName metódus.
Több meghívást fogad el.
Igény szerint a MethodName Async paraméterrel azonos MethodNameAsync-túlterhelést is definiálhat, de egy további objektumértékkel rendelkező paraméterrel, az úgynevezett .userState
Ezt akkor tegye, ha készen áll a metódus több egyidejű meghívásának kezelésére, ebben az esetben az userState
érték vissza lesz adva az összes eseménykezelőnek a metódus meghívásainak megkülönböztetése érdekében. Dönthet úgy is, hogy ezt egyszerűen a felhasználói állapot későbbi lekéréses tárolására szolgáló helyként teszi meg.
Minden különálló MethodNameAsync metódus-aláírás esetében:
Adja meg a következő eseményt ugyanabban az osztályban, mint a metódus:
Public Event MethodNameCompleted As MethodNameCompletedEventHandler
public event MethodNameCompletedEventHandler MethodNameCompleted;
Adja meg a következő delegáltat és AsyncCompletedEventArgs. Ezek valószínűleg az osztályon kívül lesznek definiálva, de ugyanabban a névtérben.
Public Delegate Sub MethodNameCompletedEventHandler( _ ByVal sender As Object, _ ByVal e As MethodNameCompletedEventArgs) Public Class MethodNameCompletedEventArgs Inherits System.ComponentModel.AsyncCompletedEventArgs Public ReadOnly Property Result() As MyReturnType End Property
public delegate void MethodNameCompletedEventHandler(object sender, MethodNameCompletedEventArgs e); public class MethodNameCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { public MyReturnType Result { get; } }
Győződjön meg arról, hogy a MethodNameCompletedEventArgs osztály írásvédett tulajdonságként, nem mezőként teszi elérhetővé tagjait, mivel a mezők megakadályozzák az adatkötést.
Ne definiáljon AsyncCompletedEventArgs-származtatott osztályokat olyan metódusokhoz, amelyek nem hoznak létre eredményt. Egyszerűen használjon saját példányt AsyncCompletedEventArgs .
Feljegyzés
A delegáltak és típusok újrafelhasználása – ha lehetséges és AsyncCompletedEventArgs megfelelő – tökéletesen elfogadható. Ebben az esetben az elnevezés nem lesz összhangban a metódus nevével, mivel egy adott meghatalmazott AsyncCompletedEventArgs nem lesz egyetlen metódushoz kötve.
Opcionálisan a lemondás támogatása
Ha az osztály támogatja az aszinkron műveletek megszakítását, a lemondást az alábbiak szerint közzé kell tenni az ügyfél számára. A lemondási támogatás meghatározása előtt két döntési pontot kell elérni:
- Az osztálynak, beleértve a jövőbeli várható kiegészítéseket is, csak egy aszinkron művelettel rendelkezik, amely támogatja a lemondást?
- A lemondást támogató aszinkron műveletek támogathatnak több függőben lévő műveletet? Ez azt jelenti, hogy a MethodNameAsync metódus használ egy paramétert
userState
, és engedélyezi a több meghívást, mielőtt várnia kell a befejezésre?
Az alábbi táblázatban szereplő két kérdésre adott válaszok segítségével meghatározhatja, hogy mi legyen a lemondási módszer aláírása.
Visual Basic
Több egyidejű művelet támogatott | Egyszerre csak egy művelet | |
---|---|---|
Egy aszinkron művelet a teljes osztályban | Sub MethodNameAsyncCancel(ByVal userState As Object) |
Sub MethodNameAsyncCancel() |
Több Async-művelet az osztályban | Sub CancelAsync(ByVal userState As Object) |
Sub CancelAsync() |
C#
Több egyidejű művelet támogatott | Egyszerre csak egy művelet | |
---|---|---|
Egy aszinkron művelet a teljes osztályban | void MethodNameAsyncCancel(object userState); |
void MethodNameAsyncCancel(); |
Több Async-művelet az osztályban | void CancelAsync(object userState); |
void CancelAsync(); |
Ha megadja a metódust, az CancelAsync(object userState)
ügyfeleknek óvatosnak kell lenniük az állapotértékek kiválasztásakor, hogy képesek legyenek megkülönböztetni az objektumon meghívott összes aszinkron metódust, és nem csak egyetlen aszinkron metódus összes meghívása között.
A MethodNameAsyncCancel egyszinkron műveletű verziójának elnevezése azon alapul, hogy könnyebben felfedezhető a metódus egy olyan tervezési környezetben, mint a Visual Studio IntelliSense. Ez csoportosítja a kapcsolódó tagokat, és megkülönbözteti őket más tagoktól, akiknek semmi köze az aszinkron funkciókhoz. Ha arra számít, hogy további aszinkron műveletek is megjelenhetnek a következő verziókban, érdemesebb definiálni CancelAsync
.
Ne definiáljon több metódust a fenti táblázatból ugyanabban az osztályban. Ez nem lesz értelme, vagy ez zsúfolt az osztály felülete a terjedése módszerek.
Ezek a metódusok általában azonnal visszatérnek, és előfordulhat, hogy a művelet ténylegesen leáll. A MethodName Completed esemény eseménykezelőjében a MethodNameCompletedEventArgs objektum tartalmaz egy Cancelled
mezőt, amellyel az ügyfelek megállapíthatják, hogy a lemondás történt-e.
Tartsa be az eseményalapú aszinkron minta implementálásának ajánlott eljárásaiban leírt lemondási szemantikát.
Opcionálisan az IsBusy tulajdonság támogatása
Ha az osztály nem támogatja több egyidejű meghívást, érdemes lehet egy tulajdonságot IsBusy
felfedni. Ez lehetővé teszi a fejlesztők számára annak megállapítását, hogy egy MethodNameAsync metódus fut-e anélkül, hogy kivételt észlelne a MethodNameAsync metódusból.
Tartsa be az IsBusy
eseményalapú aszinkron minta implementálásának ajánlott eljárásaiban leírt szemantikát.
Opcionálisan támogatás biztosítása a folyamatjelentéshez
Gyakran kívánatos, hogy egy aszinkron művelet jelentse a művelet közbeni előrehaladást. Az eseményalapú aszinkron minta útmutatást nyújt ehhez.
Igény szerint definiáljon egy eseményt, amelyet az aszinkron művelet elő szeretne hívni, és meghívja a megfelelő szálon. Az ProgressChangedEventArgs objektum egy egész szám értékű folyamatjelzőt hordoz, amely várhatóan 0 és 100 között lesz.
Nevezze el az eseményt az alábbiak szerint:
ProgressChanged
ha az osztály több aszinkron művelettel rendelkezik (vagy várhatóan több aszinkron műveletet fog tartalmazni a jövőbeli verziókban);MethodNameProgressChanged , ha az osztály egyetlen aszinkron művelettel rendelkezik.
Ez az elnevezési választási párhuzam a lemondási módszerhez készült, az Opcionális támogatás lemondása szakaszban leírtak szerint.
Ennek az eseménynek a meghatalmazotti aláírást ProgressChangedEventHandler és az osztályt kell használnia ProgressChangedEventArgs . Másik lehetőségként, ha megadhat egy tartományspecifikusabb állapotjelzőt (például olvasási bájtokat és teljes bájtokat egy letöltési művelethez), akkor meg kell határoznia a származtatott osztályt ProgressChangedEventArgs.
Vegye figyelembe, hogy az osztályhoz csak egy ProgressChanged
vagy MethodNameProgressChanged esemény tartozik, függetlenül attól, hogy hány aszinkron metódust támogat. Az ügyfeleknek a userState
MethodNameAsync metódusnak átadott objektumot kell használniuk, hogy megkülönböztessék a folyamatban lévő frissítéseket több egyidejű műveleten.
Előfordulhatnak olyan helyzetek, amikor több művelet támogatja az előrehaladást, és mindegyik egy másik mutatót ad vissza a haladáshoz. Ebben az esetben egyetlen ProgressChanged
esemény nem megfelelő, és több eseményt is támogathat ProgressChanged
. Ebben az esetben a MethodNameProgressChanged elnevezési mintáját használja az egyes MethodNameAsync metódusokhoz.
Tartsa be az eseményalapú aszinkron minta implementálásának ajánlott eljárásait ismertető folyamatjelentési szemantikát.
Igény szerint támogatás megadása növekményes eredmények visszaadására
Néha az aszinkron művelet a befejezés előtt növekményes eredményeket ad vissza. A forgatókönyv támogatásához számos lehetőség használható. Néhány példát követünk.
Egyműveletes osztály
Ha az osztály csak egyetlen aszinkron műveletet támogat, és ez a művelet növekményes eredményeket tud visszaadni, akkor:
Bővítse ki a ProgressChangedEventArgs típust a növekményes eredményadatok hordozásához, és definiáljon egy MethodNameProgressChanged eseményt ezzel a kiterjesztett adatokkal.
Növelje ezt a MethodNameProgressChanged eseményt , ha növekményes eredményt szeretne jelenteni.
Ez a megoldás kifejezetten egy aszinkron műveleti osztályra vonatkozik, mivel nem okoz problémát ugyanaz az esemény, amely növekményes eredményeket ad vissza az "összes műveleten", ahogyan a MethodNameProgressChanged esemény teszi.
Többműveletes osztály homogén növekményes eredményekkel
Ebben az esetben az osztály több aszinkron metódust támogat, amelyek mindegyike képes növekményes eredményeket visszaadni, és ezek a növekményes eredmények mindegyike ugyanolyan típusú adatokkal rendelkezik.
Kövesse a fent leírt modellt az egyműveletes osztályok esetében, mivel minden növekményes eredménynél ugyanaz EventArgs a struktúra működik. Adjon meg egy eseményt ProgressChanged
a MethodNameProgressChanged esemény helyett, mivel több aszinkron metódusra vonatkozik.
Többműveletes osztály heterogén növekményes eredményekkel
Ha az osztály több aszinkron metódust támogat, mindegyik más típusú adatot ad vissza, a következőket kell tenni:
Válassza el a növekményes eredményjelentést a folyamatjelentéstől.
Adjon meg egy külön MethodNameProgressChanged eseményt az egyes aszinkron metódusokhoz a EventArgs metódus növekményes eredményadatainak kezeléséhez.
Hívja meg ezt az eseménykezelőt a megfelelő szálon az eseményalapú aszinkron minta implementálásának ajánlott eljárásaiban leírtak szerint.
Out and Ref Parameters in Methods (Out and Ref Parameters in Methods) kezelése
Bár a .NET használata out
és ref
használata általában elriasztja őket, a következő szabályokat kell követni, amikor jelen vannak:
A MethodName szinkron metódust használva:
out
A MethodName paraméterei nem lehetnek a MethodNameAsync részei. Ehelyett a MethodNameCompletedEventArgs elemnek kell lenniük, amelynek neve megegyezik a MethodName paraméterével (hacsak nincs megfelelőbb név).ref
A MethodName paramétereinek a MethodNameAsync részeként, valamint a MethodName CompletedEventArgs metódusnév részeként kell megjelennie, amelynek a paramétere megegyezik a MethodName paraméterével (hacsak nincs megfelelőbb név).
Például:
Public Function MethodName(ByVal arg1 As String, ByRef arg2 As String, ByRef arg3 As String) As Integer
public int MethodName(string arg1, ref string arg2, out string arg3);
Az aszinkron metódus és osztálya AsyncCompletedEventArgs a következőképpen nézne ki:
Public Sub MethodNameAsync(ByVal arg1 As String, ByVal arg2 As String)
Public Class MethodNameCompletedEventArgs
Inherits System.ComponentModel.AsyncCompletedEventArgs
Public ReadOnly Property Result() As Integer
End Property
Public ReadOnly Property Arg2() As String
End Property
Public ReadOnly Property Arg3() As String
End Property
End Class
public void MethodNameAsync(string arg1, string arg2);
public class MethodNameCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
{
public int Result { get; };
public string Arg2 { get; };
public string Arg3 { get; };
}
Lásd még
- ProgressChangedEventArgs
- AsyncCompletedEventArgs
- Útmutató: Az eseményalapú aszinkron mintát támogató összetevő implementálása
- Útmutató: Művelet futtatása a háttérben
- Útmutató: Háttérműveletet használó űrlap implementálása
- Döntés az eseményalapú aszinkron minta implementálásáról
- Ajánlott eljárások az eseményalapú aszinkron minta implementálására
- Eseményalapú aszinkron minta (EAP)
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: