Návod: Vytvoření jednoduché vícevláknové komponenty pomocí sady Visual Basic
BackgroundWorker Nahrazuje součásti a funkce přidá System.Threading obor názvů. však System.Threading oboru názvů je zachována z důvodu zpětné kompatibility a budoucí použití rozhodnete.Další informace naleznete v tématu BackgroundWorker – přehled komponenty.
Můžete psát aplikace, které jsou schopny provádět více úloh současně.Tato možnost nazývá multithreading, nebo volného zřetězení, je efektivní způsob návrhu komponent, které jsou náročné na procesor a vyžadovat vstup uživatele.Příklad součásti, která může být použití multithreading by součást, která vypočítá mzdové informace.Komponenta může zpracovávat data do databáze zadána uživatelem v jednom podprocesu během mezd náročné výpočty byly provedeny na jiném.Spuštěním těchto procesů oddělené podprocesy uživatelé nemusí čekat na dokončení výpočtů před zadáním dat. Další počítače.V tomto návodu vytvoříte jednoduchý podprocesy součást, která provádí složité výpočty více současně.
Vytváření projektu
Aplikace bude sestávat z jediného formuláře a komponenty.Uživatel zadá hodnoty a signál součásti začít výpočty.Formulář pak zobrazí hodnoty z komponenty a jejich zobrazení v popisku.Komponenta bude provádět náročné výpočty a signál po dokončení formuláře.Veřejné proměnné vytvořené v komponentě uložit hodnoty, z uživatelského rozhraní.Bude také implementovat metody v komponentě provádět výpočty na základě hodnot těchto proměnných.
[!POZNÁMKA]
Funkce je obvykle výhodnější pro metodu, která vypočítá hodnotu, argumenty nelze předávat mezi podprocesy ani mohou být vráceny hodnoty.Mnoha způsoby jednoduché hodnoty podprocesům a přijímat jejich hodnoty.V této ukázce aktualizací veřejné proměnné budou vracet hodnoty uživatelského rozhraní a události bude informovat hlavní program po dokončení spuštění podprocesu.
Dialogová okna a příkazy v nabídkách menu, které vidíte, se mohou lišit od těch popsaných v nápovědě, v závislosti na vašich aktivních nastaveních nebo edici.Chcete-li změnit nastavení, zvolte Import and Export Settings v menu Nástroje.Další informace naleznete v tématu Přizpůsobení nastavení pro vývoj v sadě Visual Studio.
Chcete-li vytvořit formulář
Vytvoření nového Aplikace systému Windows projektu.
Název aplikace Calculations a přejmenujte Form1.vb jako frmCalculations.vb .
Při aplikaci Visual Studio vás vyzve k přejmenování Form1 kód prvek, klepněte na tlačítko Ano.
Tento formulář bude sloužit jako primární uživatelské rozhraní aplikace.
Pět Label řídí čtyři Button ovládací prvky a jeden TextBox ovládacího prvku do formuláře.
Ovládací prvek
Název
Text
Label1
lblFactorial1
(prázdné)
Label2
lblFactorial2
(prázdné)
Label3
lblAddTwo
(prázdné)
Label4
lblRunLoops
(prázdné)
Label5
lblTotalCalculations
(prázdné)
Button1
btnFactorial1
Faktoriálu
Button2
btnFactorial2
Faktoriálu - 1
Button3
btnAddTwo
Přidejte dvě
Button4
btnRunLoops
Spuštění smyčky
TextBox1
txtValue
(prázdné)
Vytvoření komponenty programu Kalkulačka
Z projektu nabídce Přidat součást.
Název této součásti Calculator .
Přidat součást Kalkulačka veřejné proměnné
Otevřít Editor kódu pro Calculator .
Přidejte příkazy k vytvoření veřejné proměnné, které budete používat k předání hodnoty z frmCalculations pro každý podproces.
Proměnná varTotalCalculations bude udržovat průběžný součet celkového počtu výpočty prováděné komponenty a jiné proměnné bude přijímat hodnoty z formuláře.
Public varAddTwo As Integer Public varFact1 As Integer Public varFact2 As Integer Public varLoopValue As Integer Public varTotalCalculations As Double = 0
Přidání metod a událostí součásti programu Kalkulačka
Události, které komponenta bude používat ke komunikaci hodnot do formuláře Deklarujte.Bezprostředně pod deklarace proměnných zadali v předchozím kroku zadejte následující kód:
Public Event FactorialComplete(ByVal Factorial As Double, ByVal _ TotalCalculations As Double) Public Event FactorialMinusComplete(ByVal Factorial As Double, ByVal _ TotalCalculations As Double) Public Event AddTwoComplete(ByVal Result As Integer, ByVal _ TotalCalculations As Double) Public Event LoopComplete(ByVal TotalCalculations As Double, ByVal _ Counter As Integer)
Bezprostředně pod deklarace proměnných zadané v kroku 1, zadejte následující kód:
' This sub will calculate the value of a number minus 1 factorial ' (varFact2-1!). Public Sub FactorialMinusOne() Dim varX As Integer = 1 Dim varTotalAsOfNow As Double Dim varResult As Double = 1 ' Performs a factorial calculation on varFact2 - 1. For varX = 1 to varFact2 - 1 varResult *= varX ' Increments varTotalCalculations and keeps track of the current ' total as of this instant. varTotalCalculations += 1 varTotalAsOfNow = varTotalCalculations Next varX ' Signals that the method has completed, and communicates the ' result and a value of total calculations performed up to this ' point RaiseEvent FactorialMinusComplete(varResult, varTotalAsOfNow) End Sub ' This sub will calculate the value of a number factorial (varFact1!). Public Sub Factorial() Dim varX As Integer = 1 Dim varResult As Double = 1 Dim varTotalAsOfNow As Double = 0 For varX = 1 to varFact1 varResult *= varX varTotalCalculations += 1 varTotalAsOfNow = varTotalCalculations Next varX RaiseEvent FactorialComplete(varResult, varTotalAsOfNow) End Sub ' This sub will add two to a number (varAddTwo + 2). Public Sub AddTwo() Dim varResult As Integer Dim varTotalAsOfNow As Double varResult = varAddTwo + 2 varTotalCalculations += 1 varTotalAsOfNow = varTotalCalculations RaiseEvent AddTwoComplete(varResult, varTotalAsOfNow) End Sub ' This method will run a loop with a nested loop varLoopValue times. Public Sub RunALoop() Dim varX As Integer Dim varY As Integer Dim varTotalAsOfNow As Double For varX = 1 To varLoopValue ' This nested loop is added solely for the purpose of slowing ' down the program and creating a processor-intensive ' application. For varY = 1 To 500 varTotalCalculations += 1 varTotalAsOfNow = varTotalCalculations Next Next RaiseEvent LoopComplete(varTotalAsOfNow, varX - 1) End Sub
Přenos vstup uživatele součásti
Dalším krokem je přidání kódu frmCalculations pro vstup od uživatele a pro přenos a příjem hodnoty do a z Calculator komponent.
K implementaci klientské funkce frmCalculations
Vyberte Sestavit řešení z sestavení nabídce.
Otevřít frmCalculations v Návrháři model Windows Forms.
Vyhledejte Výpočty komponent v kartě panel.Přetáhněte Kalkulačka na povrch návrhové komponenty.
V Vlastnosti systému windows, klepněte události tlačítko.
Poklepejte na čtyři události vytvoření obslužné rutiny událostí v frmCalculations .Musíte vrátit Návrhář po každé obslužnou rutinu události.
Vložte následující kód pro zpracování událostí formuláře obdrží od Calculator1 :
Private Sub Calculator1_AddTwoComplete(ByVal Result As System.Int32, ByVal TotalCalculations As System.Double) Handles Calculator1.AddTwoComplete lblAddTwo.Text = Result.ToString btnAddTwo.Enabled = True lblTotalCalculations.Text = "TotalCalculations are " & _ TotalCalculations.ToString End Sub Private Sub Calculator1_FactorialComplete(ByVal Factorial As System.Double, ByVal TotalCalculations As System.Double) Handles Calculator1.FactorialComplete ' Displays the returned value in the appropriate label. lblFactorial1.Text = Factorial.ToString ' Re-enables the button so it can be used again. btnFactorial1.Enabled = True ' Updates the label that displays the total calculations performed lblTotalCalculations.Text = "TotalCalculations are " & _ TotalCalculations.ToString End Sub Private Sub Calculator1_FactorialMinusComplete(ByVal Factorial As System.Double, ByVal TotalCalculations As System.Double) Handles Calculator1.FactorialMinusComplete lblFactorial2.Text = Factorial.ToString btnFactorial2.Enabled = True lblTotalCalculations.Text = "TotalCalculations are " & _ TotalCalculations.ToString End Sub Private Sub Calculator1_LoopComplete(ByVal TotalCalculations As System.Double, ByVal Counter As System.Int32) Handles Calculator1.LoopComplete btnRunLoops.Enabled = True lblRunLoops.Text = Counter.ToString lblTotalCalculations.Text = "TotalCalculations are " & _ TotalCalculations.ToString End Sub
Vyhledejte End Class prohlášení v dolní části Editor kódu.Bezprostředně nad ním, přidejte následující kód pro zpracování klepnutí na tlačítka:
Private Sub btnFactorial1_Click(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles btnFactorial1.Click ' Passes the value typed in the txtValue to Calculator.varFact1. Calculator1.varFact1 = CInt(txtValue.Text) ' Disables the btnFactorial1 until this calculation is complete. btnFactorial1.Enabled = False Calculator1.Factorial() End Sub Private Sub btnFactorial2_Click(ByVal sender As Object, ByVal e _ As System.EventArgs) Handles btnFactorial2.Click Calculator1.varFact2 = CInt(txtValue.Text) btnFactorial2.Enabled = False Calculator1.FactorialMinusOne() End Sub Private Sub btnAddTwo_Click(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles btnAddTwo.Click Calculator1.varAddTwo = CInt(txtValue.Text) btnAddTwo.Enabled = False Calculator1.AddTwo() End Sub Private Sub btnRunLoops_Click(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles btnRunLoops.Click Calculator1.varLoopValue = CInt(txtValue.Text) btnRunLoops.Enabled = False ' Lets the user know that a loop is running. lblRunLoops.Text = "Looping" Calculator1.RunALoop() End Sub
Testování aplikace
Nyní jste vytvořili projekt, který zahrnuje formulář a součást provést několik složitých výpočtů.Přestože multithreading funkce nebyla implementována ještě ověřit jeho funkčnost před pokračováním projektu bude test.
Testování projektu
Z ladění nabídce zvolte Spustit ladění.Začne aplikace a frmCalculations se zobrazí.
Do textového pole zadejte 4, klepněte na tlačítko s názvem Přidat dva.
Číslicí "6" má být zobrazen v popisku pod ní a "Celkové výpočty jsou 1" zobrazí v lblTotalCalculations .
Nyní klepněte na tlačítko faktoriálu - 1.
Číslo "6" by měl být zobrazen pod tlačítko, a lblTotalCalculations nyní přečte "Celková výpočty jsou 4".
Změňte hodnotu v textovém poli na 20, klepněte na tlačítko s názvem faktoriálu.
Zobrazí se číslo "2.43290200817664E + 18" pod ní, a lblTotalCalculations nyní přečte "Jsou výpočty celkem 24."
Změňte hodnotu v textovém poli na 50000a klepněte na tlačítko s názvem Spuštění smyčky a.
Všimněte si, že malé ale znatelný interval před klepnutím na toto tlačítko znovu povolena."50000" Určen štítku podle tohoto tlačítka a zobrazí celkový výpočty jsou "25000024"
Změňte hodnotu v textovém poli na 5 000 000 a klepněte na tlačítko Spuštění smyčky aa ihned klepněte na tlačítko Přidat dva.Klepněte na tlačítko Přidat dva znovu.
Tlačítko nereaguje ani libovolného ovládacího prvku formuláře odpoví dokud smyčky.
Pokud se program spustí pouze jeden podproces provádění, náročné výpočty, například výše uvedený příklad mají tendenci k programu dokud výpočty.V další části se přidat multithreading schopnost aplikace tak, aby více podprocesů může běžet současně.
Přidání Multithreading schopnost
V předchozím příkladu prokázáno omezení aplikace, které pracují pouze jediný podproces provádění.V další části se budou používat Thread třídy komponenty přidat více podprocesů spuštění.
Chcete-li přidat podprogram podprocesů
Otevřít Calculator.vb v Editor kódu.V horní části kód vyhledejte Public Class Calculator řádku.Bezprostředně pod ním, zadejte následující příkaz:
' Declares the variables you will use to hold your thread objects. Public FactorialThread As System.Threading.Thread Public FactorialMinusOneThread As System.Threading.Thread Public AddTwoThread As System.Threading.Thread Public LoopThread As System.Threading.Thread
Bezprostředně před End Class prohlášení v dolní části kódu, přidejte následující metodu:
Public Sub ChooseThreads(ByVal threadNumber As Integer) ' Determines which thread to start based on the value it receives. Select Case threadNumber Case 1 ' Sets the thread using the AddressOf the subroutine where ' the thread will start. FactorialThread = New System.Threading.Thread(AddressOf _ Factorial) ' Starts the thread. FactorialThread.Start() Case 2 FactorialMinusOneThread = New _ System.Threading.Thread(AddressOf FactorialMinusOne) FactorialMinusOneThread.Start() Case 3 AddTwoThread = New System.Threading.Thread(AddressOf AddTwo) AddTwoThread.Start() Case 4 LoopThread = New System.Threading.Thread(AddressOf RunALoop) LoopThread.Start() End Select End Sub
Když Thread je vytvořena instance objektu, vyžaduje argument ve formě ThreadStart objektu.ThreadStart Delegát odkazující na adresu podprogram kde má začít podproces je objekt.A ThreadStart objektu nelze převzít parametry nebo hodnoty průchodu a tedy nelze označit funkci.AddressOf – operátor (Visual Basic) Vrátí delegát, který slouží jako ThreadStart objektu. ChooseThreads Sub právě implementováno bude získat hodnotu z programu je volání a tuto hodnotu použít k určení vhodných podproces spuštění.
Přidat kód spuštění podprocesu frmCalculations
Otevřít frmCalculations.vb v souboru Editor kódu.Locate Sub btnFactorial1_Click.
Řádek, který volá komentář Calculator1.Factorial přímo podle metody:
' Calculator1.Factorial
Přidejte následující řádek volání Calculator1.ChooseThreads metoda:
' Passes the value 1 to Calculator1, thus directing it to start the ' correct thread. Calculator1.ChooseThreads(1)
Provádět podobné úpravy druhé button_click podprogramy.
[!POZNÁMKA]
Nezapomeňte uvést hodnotu odpovídající threads argument.
Po dokončení, by měl vypadat jako následující kód:
Private Sub btnFactorial1_Click(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles btnFactorial1.Click ' Passes the value typed in the txtValue to Calculator.varFact1. Calculator1.varFact1 = CInt(txtValue.Text) ' Disables the btnFactorial1 until this calculation is complete. btnFactorial1.Enabled = False ' Calculator1.Factorial() ' Passes the value 1 to Calculator1, thus directing it to start the ' Correct thread. Calculator1.ChooseThreads(1) End Sub Private Sub btnFactorial2_Click(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles btnFactorial2.Click Calculator1.varFact2 = CInt(txtValue.Text) btnFactorial2.Enabled = False ' Calculator1.FactorialMinusOne() Calculator1.ChooseThreads(2) End Sub Private Sub btnAddTwo_Click(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles btnAddTwo.Click Calculator1.varAddTwo = CInt(txtValue.Text) btnAddTwo.Enabled = False ' Calculator1.AddTwo() Calculator1.ChooseThreads(3) End Sub Private Sub btnRunLoops_Click(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles btnRunLoops.Click Calculator1.varLoopValue = CInt(txtValue.Text) btnRunLoops.Enabled = False ' Lets the user know that a loop is running. lblRunLoops.Text = "Looping" ' Calculator1.RunALoop() Calculator1.ChooseThreads(4) End Sub
Zařazování volání ovládacích prvků
Nyní vám usnadní aktualizaci zobrazení ve formuláři.Protože ovládací prvky jsou majetkem vždy hlavní podproces provádění, vyžaduje každé volání ovládacího prvku z podřízeného podprocesu zařazování volání.Zařazování je úkon, přesunutí volání přes hranice podprocesu a je velmi náročné prostředcích.Minimalizace množství zařazování, který potřebuje dochází a ujistěte se, že volání jsou zpracovány v podprocesu, můžete použít BeginInvoke k vyvolání metod na hlavní podproces provádění, a tím minimalizace množství podproces přeshraniční, zařazování musí dojít.Tento druh volání je nutné při volání metody umožňující pracovat s prvky.Další informace naleznete v tématu Postupy: Manipulace s ovládacími prvky z vláken.
Chcete-li vytvořit postupy řízení volání
Otevřít Editor kódu pro frmCalculations .V sekci deklarací přidejte následující kód.
Public Delegate Sub FHandler(ByVal Value As Double, ByVal _ Calculations As Double) Public Delegate Sub A2Handler(ByVal Value As Integer, ByVal _ Calculations As Double) Public Delegate Sub LDhandler(ByVal Calculations As Double, ByVal _ Count As Integer)
Invokea BeginInvoke vyžadují delegát vhodné metody jako argument.Tyto řádky delegáta deklarovat, podpisy, které budou použity v BeginInvoke vyvolat vhodných metod.
Přidejte následující metody prázdný kód.
Public Sub FactHandler(ByVal Factorial As Double, ByVal TotalCalculations As _ Double) End Sub Public Sub Fact1Handler(ByVal Factorial As Double, ByVal TotalCalculations As _ Double) End Sub Public Sub Add2Handler(ByVal Result As Integer, ByVal TotalCalculations As _ Double) End Sub Public Sub LDoneHandler(ByVal TotalCalculations As Double, ByVal Counter As _ Integer) End Sub
Z Upravit nabídce použít Vyjmout a Vložit k vyjmutí kódu z Sub Calculator1_FactorialComplete a vložit jej do FactHandler .
Repeat the previous step for Calculator1_FactorialMinusComplete and Fact1Handler, Calculator1_AddTwoComplete and Add2Handler, and Calculator1_LoopComplete and LDoneHandler.
Po dokončení by měla být žádný kód zbývající v Calculator1_FactorialComplete , Calculator1_FactorialMinusComplete , Calculator1_AddTwoComplete , a Calculator1_LoopComplete a všechny tyto obsahoval by byly přesunuty do nové vhodné metody kódu.
Volání BeginInvoke metoda vyvolat metody asynchronně.Můžete volat BeginInvoke buď z formuláře (me) nebo ovládacích prvků ve formuláři:
Private Sub Calculator1_FactorialComplete(ByVal Factorial As System.Double, ByVal TotalCalculations As System.Double) Handles Calculator1.FactorialComplete ' BeginInvoke causes asynchronous execution to begin at the address ' specified by the delegate. Simply put, it transfers execution of ' this method back to the main thread. Any parameters required by ' the method contained at the delegate are wrapped in an object and ' passed. Me.BeginInvoke(New FHandler(AddressOf FactHandler), New Object() _ {Factorial, TotalCalculations }) End Sub Private Sub Calculator1_FactorialMinusComplete(ByVal Factorial As System.Double, ByVal TotalCalculations As System.Double) Handles Calculator1.FactorialMinusComplete Me.BeginInvoke(New FHandler(AddressOf Fact1Handler), New Object() _ { Factorial, TotalCalculations }) End Sub Private Sub Calculator1_AddTwoComplete(ByVal Result As System.Int32, ByVal TotalCalculations As System.Double) Handles Calculator1.AddTwoComplete Me.BeginInvoke(New A2Handler(AddressOf Add2Handler), New Object() _ { Result, TotalCalculations }) End Sub Private Sub Calculator1_LoopComplete(ByVal TotalCalculations As System.Double, ByVal Counter As System.Int32) Handles Calculator1.LoopComplete Me.BeginInvoke(New LDHandler(AddressOf Ldonehandler), New Object() _ { TotalCalculations, Counter }) End Sub
To může zdát obslužná rutina události je jednoduše volání k další metodě.Obslužná rutina události skutečně způsobuje metoda vyvolat v hlavní podproces operace.Tento přístup se uloží na volání přes hranice podprocesu a umožňuje spouštění účinně a bez obav způsobit zamrznutí podprocesy aplikací.Podrobné informace o práci s ovládacími prvky v prostředí s více podprocesy, viz Postupy: Manipulace s ovládacími prvky z vláken.
Uložte svou práci.
Test řešení výběrem Spustit ladění z ladění nabídce.
Typ 10000000 v textovém poli a klepněte na Spuštění smyčky a.
"Opakování" je zobrazený v popisku pod toto tlačítko.Tento cyklus brát značné množství času spuštění.Pokud dokončí příliš brzy, odpovídajícím způsobem upravte velikost čísla.
Rychle za sebou klepněte na všechny tři tlačítka, které jsou stále povoleny.Zjistíte, že všechna tlačítka odpovědět vstup.Popisek pod Přidat dva by měl být první zobrazení výsledku.Výsledky budou zobrazeny později v popiscích pod faktoriálu tlačítka.Tyto výsledky vyhodnotit do nekonečna, jako je příliš velký pro proměnnou s dvojitou přesností obsahovat číslo vrácené 10,000,000 faktoriálu.Nakonec další zpožděním výsledky pod Spuštění smyčky a tlačítko.
Jako je právě pozorovaných čtyři samostatné sady výpočty byly prováděny současně čtyři oddělené podprocesy.Uživatelské rozhraní zůstala reagovat na vstup a byly vráceny po každý podproces dokončena.
Koordinovat své podprocesů
Zkušení uživatelé s více podprocesy aplikací může vnímat decentní chyba s kódem jako zadali.Odvolání řádky kódu z každé provedení výpočtu podprogram v Calculator :
varTotalCalculations += 1
varTotalAsOfNow = varTotalCalculations
Tyto dva řádky kódu zvýšit veřejné proměnné varTotalCalculations a nastavte místní proměnné varTotalAsOfNow na tuto hodnotu.Tato hodnota je poté zaslána frmCalculations a zobrazeny v ovládacím prvku popisek.Ale je správné hodnoty vracené?Pokud pouze jeden podproces provádění je spuštěn, je jasně odpověď Ano.Ale pokud více podprocesů, odpověď se stává více neurčité.Každý podproces má možnost zvýšit proměnnou varTotalCalculations .Je možné, že po jeden podproces zvýší tuto proměnnou, ale před zkopíruje hodnotu na varTotalAsOfNow , jiný podproces mohly zvětšením je hodnota této proměnné.To vede k možnost každý podproces je ve skutečnosti vykazování nepřesné výsledky.Visual Basic poskytuje SyncLock – příkaz povolení synchronizace podprocesů, aby každý podproces vrací vždy přesné výsledky.Syntaxe funkce SyncLock je následující:
SyncLock AnObject
Insert code that affects the object
Insert some more
Insert even more
' Release the lock
End SyncLock
Když SyncLock bloku je zapsáno, spuštění zadaného výrazu blokována, dokud Zadaný podproces má výhradní zámek u daného objektu.Ve výše uvedeném příkladu je blokováno spuštění na AnObject .SyncLockmusí být použita s objektem, který vrací odkaz, nikoli hodnotu.Provádění pokračovat potom blok bez rušení z jiných podprocesů.Sadu příkazů, které jako celek, jsou označeny jako atomovou.Při End SyncLock je zjistil, uvolněno výraz a podprocesy mohou pokračovat normálně.
Přidat příkaz SyncLock aplikace
Otevřít Calculator.vb v Editor kódu.
Vyhledejte každou instanci následující kód:
varTotalCalculations += 1 varTotalAsOfNow = varTotalCalculations
Měl by být čtyři instance tohoto kódu, jeden v každé metody výpočtu.
Tento kód upravte tak, aby se nahrazuje tímto:
SyncLock Me varTotalCalculations += 1 varTotalAsOfNow = varTotalCalculations End SyncLock
Uložte práci a vyzkoušet jako v předchozím příkladu.
Můžete zaznamenat mírné dopad na výkon aplikace.Důvodem je provádění podprocesů zastavíte na komponenty se získá výhradní zámek.Přestože zajišťuje přesnost, tento přístup brání některé výhoda více podprocesů.By měly pečlivě zvážit potřebu zamykání podprocesů a je pouze v krajním případě provede.
Viz také
Úkoly
Postupy: Koordinace více vláken provádění
Návod: Vytvoření jednoduché vícevláknové komponenty pomocí Visual C#
Referenční dokumentace
Koncepty
Přehled asynchronních vzorů založených na událostech