Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
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óért a BackgroundWorker-ról lásd: Hogyan kell: 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
Az out és ref paraméterek kezelése metódusokban
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 és IAsyncResult objektumokra aszinkron műveletekhez, ami azt jelenti, hogy az ügyfélnek kell kialakítania a lekérdezést, és létrehoznia WaitAll vagy WaitAny.
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:
Visszatér
void.Ugyanazokat a paramétereket veszi fel, mint a MethodName metódus.
Több meghívást fogad el.
Igény szerint definiálhat egy `MethodNameAsync` túlterhelést, amely azonos `MethodNameAsync`-szal, de kiegészül egy további objektumértékkel rendelkező paraméterrel. 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 MethodNameCompletedEventHandlerpublic 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 Propertypublic 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 egy példányt AsyncCompletedEventArgs önmagában.
Megjegyzés:
A delegáltak és AsyncCompletedEventArgs típusok újrafelhasználása – ha lehetséges és megfelelő – tökéletesen elfogadható. Ebben az esetben az elnevezés nem lesz olyan következetes a függvény nevével, mivel egy adott delegált és AsyncCompletedEventArgs nem lesz egyetlen függvényhez 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 elfogad egy
userStateparamétert, és lehetővé teszi a többszöri meghívást, mielőtt várna bármelyik befejezésére?
Az alábbi táblázatban szereplő két kérdésre adott válaszok segítségével meghatározhatja, hogy milyen legyen a visszavonási módszer szignálási módja.
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. Ennek így nincs értelme, vagy zsúfolttá teszi az osztály felületét a módszerek elburjánzása.
Ezek a metódusok általában azonnal visszatérnek, és előfordulhat, hogy a művelet ténylegesen leáll. A MethodNameCompleted 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 IsBusy tulajdonságot elérhetővé tenni. 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 IsBusyesemé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:
ProgressChangedha 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 döntés párhuzamos a lemondási módszerrel, ahogyan azt az „Opcionálisan támogassa a lemondást” szakasz leírja.
Ennek az eseménynek a ProgressChangedEventHandler delegált aláírást és a ProgressChangedEventArgs osztályt kell használnia. 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 userStateMethodNameAsync 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 megfontolhatja több ProgressChanged esemény támogatását. 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 ProgressChanged eseményt a MethodNameProgressChanged esemény helyett, mivel több aszinkron metódusra is 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.
Definiáljon külön MethodNameProgressChanged eseményt az egyes aszinkron metódusok számára, a megfelelő EventArgs használatával a 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.
Az out és ref paraméterek kezelése metódusokban
Bár a out és ref használata általában nem ajánlott a .NET-ben, vannak szabályok, amelyeket követni kell, amikor jelen vannak.
A MethodName szinkron metódust használva:
outA 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).refA MethodName paramétereinek a MethodNameAsync részeként, valamint a MethodNameCompletedEventArgs 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)