Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Pokud píšete třídu s některými operacemi, které můžou způsobovat znatelné zpoždění, zvažte poskytnutí asynchronní funkčnosti implementací Asynchronního vzoru založeného na událostech.
Asynchronní vzor založený na událostech poskytuje standardizovaný způsob balení třídy, která má asynchronní funkce. Pokud je implementováno s pomocnými třídami, jako je AsyncOperationManager, vaše třída bude fungovat správně v libovolném aplikačním modelu, včetně ASP.NET, konzolových aplikací a aplikací Modelu Windows Forms.
Příklad, který implementuje asynchronní vzor založený na událostech, viz Postupy: Implementace komponenty, která podporuje asynchronní vzor založený na událostech.
U jednoduchých asynchronních operací můžete najít vhodný komponentu BackgroundWorker . Další informace o BackgroundWorkerviz Jak na to: Spuštění operace na pozadí.
Následující seznam popisuje funkce asynchronního vzoru založeného na událostech popsaných v tomto tématu.
Příležitosti k implementaci asynchronního vzoru založeného na událostech
Pojmenování asynchronních metod
Volitelně můžete podporovat zrušení.
Volitelně podporuje vlastnost IsBusy
Volitelně můžete poskytnout podporu pro vykazování průběhu.
Volitelně můžete poskytnout podporu pro vracení přírůstkových výsledků.
Zpracování parametrů out a ref v metodách
Příležitosti k implementaci asynchronního vzoru založeného na událostech
Zvažte implementaci asynchronního vzoru založeného na událostech v následujících případech:
Klienti vaší třídy nepotřebují WaitHandle a IAsyncResult objekty dostupné pro asynchronní operace, což znamená, že dotazování a WaitAll nebo WaitAny bude nutné sestavit klientem.
Chcete, aby klient řídil asynchronní operace pomocí známého modelu událostí a delegátů.
Každá operace může být kandidátem pro asynchronní implementaci, ale ty, u kterých očekáváte dlouhé latence, by se měly zvážit. Zvláště vhodné jsou operace, při nichž klienti volají metodu a jsou upozorněni na její dokončení, aniž by byl vyžadován další zásah. Vhodné jsou také operace, které běží nepřetržitě, pravidelně upozorňují klienty na průběh, přírůstkové výsledky nebo změny stavu.
Další informace o rozhodování o tom, kdy podporovat asynchronní vzor založený na událostech, naleznete v tématu Rozhodování o implementaci asynchronního vzoru založeného na událostech.
Pojmenování asynchronních metod
Pro každou synchronní metodu MethodName , pro kterou chcete poskytnout asynchronní protějšek:
Definujte metodu MethodNameAsync , která:
Vrátí
void.Vezme stejné parametry jako MethodName metoda.
Přijímá více vyvolání.
Volitelně definujte přetížení MethodNameAsync , shodné s MethodNameAsync, ale s dalším parametrem s hodnotou objektu volaným userState. Pokud jste připraveni řídit více souběžných vyvolání vaší metody, v takovém případě bude hodnota userState doručena zpět všem obslužným rutinám událostí k odlišení vyvolání metody. Můžete se také rozhodnout, že to uděláte jednoduše jako místo pro uložení stavu uživatele pro pozdější načtení.
Pro každý samostatný podpis metody MethodNameAsync :
Definujte následující událost ve stejné třídě jako metoda:
Public Event MethodNameCompleted As MethodNameCompletedEventHandlerpublic event MethodNameCompletedEventHandler MethodNameCompleted;Definujte následující delegáta a AsyncCompletedEventArgs. Ty budou pravděpodobně definovány mimo samotnou třídu, ale ve stejném oboru názvů.
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; } }Ujistěte se, že MethodNameCompletedEventArgs třída zveřejňuje své členy jako vlastnosti jen pro čtení, a ne pole, jako pole brání datové vazbě.
Nedefinujte žádné AsyncCompletedEventArgs-odvozené třídy pro metody, které nevytvářejí výsledky. Stačí použít instanci AsyncCompletedEventArgs samotnou.
Poznámka:
Je naprosto přijatelné, pokud je to možné a vhodné, opakovaně používat delegáta a AsyncCompletedEventArgs typy. V tomto případě nebude pojmenování tak konzistentní s názvem metody, protože daný delegát a AsyncCompletedEventArgs nebude svázán s jedinou metodou.
Volitelně můžete podporovat zrušení.
Pokud vaše třída bude podporovat zrušení asynchronních operací, zrušení by mělo být vystaveno klientovi, jak je popsáno níže. Před definováním podpory zrušení je potřeba dosáhnout dvou rozhodovacích bodů:
- Má vaše třída, včetně budoucích očekávaných přírůstků, pouze jednu asynchronní operaci, která podporuje storno?
- Mohou asynchronní operace, které podporují zrušení, podporovat více čekajících operací? To znamená, že metoda MethodNameAsync používá
userStateparametr a umožňuje několik vyvolání před čekáním na dokončení?
Pomocí odpovědí na tyto dvě otázky v tabulce níže určete, jaký podpis pro metodu zrušení má být.
Visual Basic
| Podporováno více souběžných operací | Pouze jedna operace najednou | |
|---|---|---|
| Jedna asynchronní operace v celé třídě | Sub MethodNameAsyncCancel(ByVal userState As Object) |
Sub MethodNameAsyncCancel() |
| Více asynchronních operací ve třídě | Sub CancelAsync(ByVal userState As Object) |
Sub CancelAsync() |
C#
| Podporováno více souběžných operací | Pouze jedna operace najednou | |
|---|---|---|
| Jedna asynchronní operace v celé třídě | void MethodNameAsyncCancel(object userState); |
void MethodNameAsyncCancel(); |
| Více asynchronních operací ve třídě | void CancelAsync(object userState); |
void CancelAsync(); |
Pokud definujete metodu CancelAsync(object userState) , klienti musí být opatrní při výběru jejich stavových hodnot, aby je mohli rozlišit mezi všemi asynchronními metodami vyvolanými na objektu, a ne pouze mezi všemi vyvoláním jedné asynchronní metody.
Rozhodnutí o pojmenování verze MethodNameAsyncCancel s jednou asynchronní operací je založené na tom, že je možné snadněji zjistit metodu v návrhovém prostředí, jako je IntelliSense sady Visual Studio. Tím se seskupí související členové a odliší se od ostatních členů, kteří nemají nic společného s asynchronní funkcionalitou. Pokud očekáváte, že v následujících verzích mohou být přidány další asynchronní operace, je lepší definovat CancelAsync.
Ve stejné třídě nedefinujte více metod z výše uvedené tabulky. To nebude dávat smysl, nebo to zahlcuje rozhraní třídy přemírou metod.
Tyto metody se obvykle vrátí okamžitě a operace může nebo nemusí být ve skutečnosti zrušena. V obslužné rutině události MethodNameCompleted událost, MethodNameCompletedEventArgs objekt obsahuje Cancelled pole, které klienti mohou použít k určení, zda došlo ke zrušení.
Dodržujte sémantiku zrušení popsanou v osvědčených postupech pro implementaci asynchronního vzoru založeného na událostech.
Volitelně podporuje vlastnost IsBusy
Pokud vaše třída nepodporuje více souběžných vyvolání, zvažte zveřejnění IsBusy vlastnosti. Vývojáři tak můžou určit, jestli je spuštěná metoda MethodNameAsync , aniž by zachytili výjimku z metody MethodNameAsync .
Dodržujte sémantiku IsBusy popsanou v osvědčených postupech pro implementaci asynchronního vzoru založeného na událostech.
Volitelně můžete poskytnout podporu pro vykazování průběhu.
Často je žádoucí, aby asynchronní operace hlásila průběh během jejího průběhu. Asynchronní vzor založený na událostech poskytuje vodítko k tomu.
Volitelně definujte událost, která má být vyvolána asynchronní operací a vyvolána v příslušném vlákně. Objekt ProgressChangedEventArgs nese celočíselnou hodnotu indikátor průběhu, který má být mezi 0 a 100.
Tuto událost pojmenujte následujícím způsobem:
ProgressChangedpokud má třída více asynchronních operací (nebo se očekává, že bude růst tak, aby zahrnovala více asynchronních operací v budoucích verzích);MethodNameProgressChanged , pokud třída má jednu asynchronní operaci.
Tato volba pojmenování je paralelní s tou, která byla provedena pro metodu zrušení, jak je popsáno v části Podpora volitelného zrušení.
Tato událost by měla používat podpis delegáta ProgressChangedEventHandler a třídu ProgressChangedEventArgs. Případně pokud je možné poskytnout indikátor průběhu specifický pro doménu (například bajty přečtené a celkové bajty pro operaci stahování), měli byste definovat odvozenou třídu ProgressChangedEventArgs.
Všimněte si, že pro třídu existuje pouze jedna ProgressChanged nebo MethodNameProgressChanged událost bez ohledu na počet asynchronních metod, které podporuje. Očekává se, že klienti budou používat userState objekt předaný metodám MethodNameAsync k rozlišení mezi probíhajícími aktualizacemi v několika souběžných operacích.
Může docházet k situacím, kdy více operací podporuje průběh a každý z nich vrací jiný ukazatel průběhu. V takovém případě není jedna ProgressChanged událost vhodná a můžete zvážit podporu více ProgressChanged událostí. V tomto případě použijte vzor pojmenování MethodNameProgressChanged pro každou metodu MethodNameAsync .
Dodržujte sémantiku hlášení o průběhu popsanou v Osvědčených postupech pro implementaci asynchronního vzoru na bázi událostí.
Volitelně můžete poskytnout podporu pro vracení přírůstkových výsledků.
Někdy může asynchronní operace vrátit přírůstkové výsledky před dokončením. Pro podporu tohoto scénáře je možné použít řadu možností. Následují některé příklady.
Třída jednoduché operace
Pokud vaše třída podporuje pouze jednu asynchronní operaci a tato operace dokáže vrátit přírůstkové výsledky, pak:
ProgressChangedEventArgs Rozšiřte typ tak, aby přenášel data přírůstkových výsledků, a definujte událost MethodNameProgressChanged s tímto rozšířenými daty.
Vyvolejte tuto událost MethodNameProgressChanged, když je k dispozici přírůstkový výsledek k oznámení.
Toto řešení se vztahuje konkrétně na třídu jednoduché asynchronní operace, protože není problém se stejnou událostí, která nastane pro vrácení postupných výsledků pro "všechny operace", jak to dělá událost MethodNameProgressChanged.
Třída více operací s homogenními přírůstkovými výsledky
V tomto případě vaše třída podporuje více asynchronních metod, z nichž každá dokáže vracet přírůstkové výsledky a všechny tyto přírůstkové výsledky mají stejný typ dat.
Postupujte podle výše uvedeného modelu pro třídy s jednou operací, protože stejná EventArgs struktura bude fungovat pro všechny přírůstkové výsledky.
ProgressChanged Definujte událost místo události MethodNameProgressChanged, protože se vztahuje na více asynchronních metod.
Třída vícenásobných operací s heterogenními přírůstkovými výsledky
Pokud vaše třída podporuje více asynchronních metod, každá vrací jiný typ dat, měli byste:
Oddělte podávání přírůstkových výsledků od podávání průběžných zpráv.
Definujte samostatnou událost MethodNameProgressChanged s odpovídající EventArgs pro každou asynchronní metodu pro zpracování dat přírůstkových výsledků této metody.
Vyvolání obslužné rutiny události na příslušném vlákně, jak je popsáno v osvědčených postupech pro implementaci asynchronního vzoru založeného na událostech.
Zpracování parametrů out a ref v metodách
I když je obecně nedoporučeno používat out a ref v rámci .NET, zde jsou pravidla, která je třeba dodržovat, když jsou přítomny:
Vzhledem k synchronní metodě MethodName:
outParametr methodName by neměl být součástí metody MethodNameAsync. Místo toho by měly být součástí MethodNameCompletedEventArgs se stejným názvem jako jeho ekvivalent parametru v MethodName (pokud neexistuje vhodnější název).refParametry methodName by se měly zobrazovat jako součást MethodNameAsync a jako součást MethodNameCompletedEventArgs se stejným názvem jako jeho ekvivalent parametru v MethodName (pokud neexistuje vhodnější název).
Například:
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);
Asynchronní metoda a její AsyncCompletedEventArgs třída by vypadaly takto:
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; };
}
Viz také
- ProgressChangedEventArgs
- AsyncCompletedEventArgs
- Postupy: Implementace komponenty, která podporuje asynchronní vzor založený na událostech
- Postupy: Spuštění operace na pozadí
- Postupy: Implementace formuláře, který používá operaci na pozadí
- Rozhodování o implementaci asynchronního vzoru založeného na událostech
- Osvědčené postupy pro implementaci asynchronního vzoru založeného na událostech
- Asynchronní vzor založený na událostech (EAP)