C# Multithreading Beheersen: Prestaties en Efficiëntie Verhogen
Wat is een Thread?
Threads zijn lichtgewicht processen. Een veelvoorkomend voorbeeld van thread-gebruik is de implementatie van concurrent programmeren door moderne besturingssystemen. Gebruik van threads bespaart CPU-cycli en verhoogt de efficiëntie van een applicatie.
Tot nu toe schreven we programma's waar een enkele thread draait als een enkel proces (de draaiende instantie van de applicatie). Op die manier kan de applicatie maar één taak tegelijk uitvoeren. Om meer dan één taak tegelijk uit te voeren, kan het worden opgedeeld in kleinere threads.
Thread Levenscyclus
De levenscyclus van een thread begint wanneer een object van de System.Threading.Thread klasse wordt aangemaakt en eindigt wanneer de thread wordt beëindigd of de uitvoering voltooid is.
De verschillende staten in de levenscyclus van een thread:
Unstarted State – De thread-instantie is aangemaakt maar de Start-methode is nog niet aangeroepen.
Ready State – De thread is klaar om te draaien en wacht op een CPU-cyclus.
Not Runnable State – Een thread is niet uitvoerbaar wanneer:
- Sleep-methode is aangeroepen
- Wait-methode is aangeroepen
- Geblokkeerd door I/O-operaties
Dead State – De thread heeft de uitvoering voltooid of is afgebroken.
De Main Thread
In C# wordt de System.Threading.Thread klasse gebruikt voor het werken met threads. Hiermee kun je individuele threads in een multithreaded applicatie aanmaken en benaderen. De eerste thread die in een proces wordt uitgevoerd, heet de main thread.
Wanneer een C# programma start, wordt de main thread automatisch aangemaakt. Threads die met de Thread klasse worden aangemaakt, heeten de child threads van de main thread. Je kunt een thread benaderen via de CurrentThread eigenschap van de Thread klasse.
Het volgende programma demonstreert main thread uitvoering:
using System;
using System.Threading;
namespace MultithreadingApplication {
class MainThreadProgram {
static void Main(string[] args) {
Thread th = Thread.CurrentThread;
th.Name = "MainThread";
Console.WriteLine("Dit is {0}", th.Name);
Console.ReadKey();
}
}
}
Wanneer de bovenstaande code wordt gecompileerd en uitgevoerd, produceert dit het volgende resultaat:
Dit is MainThread
Eigenschappen en Methodes van de Thread Klasse
De volgende tabel toont de meest gebruikte eigenschappen van de Thread klasse:
| Nr. | Eigenschap & Beschrijving |
|---|---|
| 1 | CurrentContext Haalt de huidige context op waarin de thread uitgevoerd wordt. |
| 2 | CurrentCulture Haalt de cultuur voor de huidige thread op of stelt deze in. |
| 3 | CurrentPrincipal Haalt de huidige principal van de thread op of stelt deze in (voor rol-gebaseerde beveiliging). |
| 4 | CurrentThread Haalt de momenteel draaiende thread op. |
| 5 | CurrentUICulture Haalt de huidige cultuur op die door de Resource Manager wordt gebruikt voor culture-specifieke resources tijdens runtime. |
| 6 | ExecutionContext Haalt een ExecutionContext-object op met informatie over de verschillende contexten van de huidige thread. |
| 7 | IsAlive Geeft een waarde terug die de uitvoeringsstatus van de huidige thread aangeeft. |
| 8 | IsBackground Haalt of stelt in of een thread een background-thread is. |
| 9 | IsThreadPoolThread Geeft aan of een thread behoort tot de managed thread pool. |
| 10 | ManagedThreadId Haalt een unieke identifier op voor de huidige managed thread. |
| 11 | Name Haalt de naam van de thread op of stelt deze in. |
| 12 | Priority Haalt of stelt de scheduling-prioriteit van een thread in. |
| 13 | ThreadState Haalt een waarde op die de staten van de huidige thread bevat. |
De volgende tabel toont de meest gebruikte methodes van de Thread klasse:
| Nr. | Methode & Beschrijving |
|---|---|
| 1 | public void Abort() Activeert een ThreadAbortException in de thread, wat het beëindigingsproces start. |
| 2 | public static LocalDataStoreSlot AllocateDataSlot() Reserveert een onbenoemde data-slot op alle threads. |
| 3 | public static LocalDataStoreSlot AllocateNamedDataSlot(string name) Reserveert een benoemde data-slot op alle threads. |
| 4 | public static void BeginCriticalRegion() Meldt aan een host dat de uitvoering een kritieke regio binnenkomt. |
| 5 | public static void BeginThreadAffinity() Meldt dat managed code instructies gaat uitvoeren die afhankelijk zijn van de identiteit van de fysieke OS-thread. |
| 6 | public static void EndCriticalRegion() Meldt dat de uitvoering een regio binnenkomt waar effecten van thread-abort beperkt zijn. |
| 7 | public static void EndThreadAffinity() Meldt dat managed code instructies heeft uitgevoerd die afhankelijk waren van de fysieke OS-thread. |
| 8 | public static void FreeNamedDataSlot(string name) Verwijderd de koppeling tussen een naam en een slot voor alle threads. |
| 9 | public static Object GetData(LocalDataStoreSlot slot) Haalt de waarde op uit de gespecificeerde slot op de huidige thread. |
| 10 | public static AppDomain GetDomain() Retourneert het huidige domein waarin de thread draait. |
| 11 | public static AppDomain GetDomainID() Retourneert een unieke applicatiedomein-identifier. |
| 12 | public static LocalDataStoreSlot GetNamedDataSlot(string name) Zoekt een benoemde data-slot op. |
| 13 | public void Interrupt() Onderbreekt een thread in de WaitSleepJoin-state. |
| 14 | public void Join() Blokkeert de aanroepende thread tot een thread beëindigd is. |
| 15 | public static void MemoryBarrier() Synchroniseert geheugentoegang. |
| 16 | public static void ResetAbort() Annuleert een aangevraagde Abort voor de huidige thread. |
| 17 | public static void SetData(LocalDataStoreSlot slot, Object data) Stelt data in de gespecificeerde slot in voor de lopende thread. |
| 18 | public void Start() Start een thread. |
| 19 | public static void Sleep(int millisecondsTimeout) Laat de thread pauzeren voor een bepaalde tijd. |
| 20 | public static void SpinWait(int iterations) Laat een thread wachten het aantal keren gedefinieerd door iterations. |
| 21 | public static byte VolatileRead(ref byte address) (en overloads) Leest de waarde van een veld, ongeacht processor-cache. |
| 22 | public static void VolatileWrite(ref byte address, byte value) (en overloads) Schrijft een waarde direct naar een veld, zichtbaar voor alle processors. |
| 23 | public static bool Yield() Laat de aanroepende thread uitvoering over aan een andere gereed thread. |
Threads Aanmaken
Threads worden aangemaakt door de Thread klasse uit te breiden. De uitgebreide Thread klasse roept vervolgens de Start() methode aan om de child thread uitvoering te beginnen.
Het volgende programma demonstreert het concept:
using System;
using System.Threading;
namespace MultithreadingApplication {
class ThreadCreationProgram {
public static void CallToChildThread() {
Console.WriteLine("Child thread start");
}
static void Main(string[] args) {
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Child thread aanmaken");
Thread childThread = new Thread(childref);
childThread.Start();
Console.ReadKey();
}
}
}
Wanneer de bovenstaande code wordt gecompileerd en uitgevoerd, produceert dit het volgende resultaat:
In Main: Child thread aanmaken Child thread start
Threads Beheren
De Thread klasse biedt diverse methodes voor het beheren van threads.
Het volgende voorbeeld demonstreert het gebruik van de Sleep() methode om een thread voor een bepaalde tijd te pauzeren:
using System;
using System.Threading;
namespace MultithreadingApplication {
class ThreadCreationProgram {
public static void CallToChildThread() {
Console.WriteLine("Child thread start");
// Thread pauzeren voor 5000 milliseconden
int sleepfor = 5000;
Console.WriteLine("Child Thread Gepauzeerd voor {0} seconden", sleepfor / 1000);
Thread.Sleep(sleepfor);
Console.WriteLine("Child thread hervat");
}
static void Main(string[] args) {
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Child thread aanmaken");
Thread childThread = new Thread(childref);
childThread.Start();
Console.ReadKey();
}
}
}
Wanneer de bovenstaande code wordt gecompileerd en uitgevoerd, produceert dit het volgende resultaat:
In Main: Child thread aanmaken Child thread start Child Thread Gepauzeerd voor 5 seconden Child thread hervat
Threads Vernietigen
De Abort() methode wordt gebruikt om threads te vernietigen.
De runtime breekt de thread af door een ThreadAbortException te gooien. Deze exception kan niet gevangen worden; de controle gaat naar de finally block, indien aanwezig.
Het volgende programma illustreert dit:
using System;
using System.Threading;
namespace MultithreadingApplication {
class ThreadCreationProgram {
public static void CallToChildThread() {
try {
Console.WriteLine("Child thread start");
// Werk doen, zoals tellen tot 10
for (int counter = 0; counter <= 10; counter++) {
Thread.Sleep(500);
Console.WriteLine(counter);
}
Console.WriteLine("Child Thread Voltooid");
} catch (ThreadAbortException e) {
Console.WriteLine("Thread Abort Exception");
} finally {
Console.WriteLine("Kon de Thread Exception niet vangen");
}
}
static void Main(string[] args) {
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Child thread aanmaken");
Thread childThread = new Thread(childref);
childThread.Start();
// Main thread pauzeren
Thread.Sleep(2000);
// Nu child thread afbreken
Console.WriteLine("In Main: Child thread afbreken");
childThread.Abort();
Console.ReadKey();
}
}
}
Wanneer de bovenstaande code wordt gecompileerd en uitgevoerd, produceert dit het volgende resultaat:
In Main: Child thread aanmaken Child thread start 0 1 2 In Main: Child thread afbreken Thread Abort Exception Kon de Thread Exception niet vangen
C Taal
- De Juiste Draadbehandeling Kiezen: Betrouwbaarheid Verhogen en Storingstijd Verminderen
- Garen: Typen, Geschiedenis, Productie en Kwaliteitscontrole
- De digitale draad ontrafelen: Siemens PLM's blauwdruk voor slimme productie
- Kleine vs Grote Draaddiameter: Hoe de Juiste Schroefgrootte te Kiezen
- Draadknippers begrijpen: Typen, toepassingen en gebruik
- Snelle Backside Illuminatie: Meer dan 1 Miljoen Frames per Seconde Vasten
- Thread vs. ZigBee: Een Technische Vergelijking voor IoT-ingenieurs
- Edge Computing Krijgt Duidelijk, Industrie-goedgekeurd Framework
- C++ Multithreading beheersen: Efficiënt gelijktijdig programmeren
- Python Multithreaded Programmering: Efficiënte Concurrency Technieken
- Java Multithreading Uitgelegd: Concepten, Levenscyclus en Praktische Codevoorbeelden