Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> C Sprache

C# Multithreading meistern: Performance & Effizienz steigern

Was ist ein Thread?

Ein Thread ist als Ausführungspfad eines Programms definiert. Jeder Thread definiert einen einzigartigen Kontrollfluss. Wenn Ihre Anwendung komplexe und zeitaufwändige Operationen umfasst, ist es oft hilfreich, verschiedene Ausführungspfade oder Threads einzurichten, wobei jeder Thread eine bestimmte Aufgabe übernimmt.

Threads sind leichtgewichtige Prozesse. Ein häufiges Beispiel für die Verwendung von Threads ist die Implementierung nebenläufiger Programmierung durch moderne Betriebssysteme. Die Verwendung von Threads spart CPU-Zyklen und erhöht die Effizienz einer Anwendung.

Bisher schrieben wir Programme, in denen ein einzelner Thread als einzelner Prozess läuft – die laufende Instanz der Anwendung. Auf diese Weise kann die Anwendung jedoch nur eine Aufgabe gleichzeitig ausführen. Um mehr als eine Aufgabe gleichzeitig auszuführen, kann sie in kleinere Threads unterteilt werden.

Thread-Lebenszyklus

Der Lebenszyklus eines Threads beginnt, wenn ein Objekt der Klasse System.Threading.Thread erstellt wird, und endet, wenn der Thread beendet wird oder die Ausführung abschließt.

Folgende Zustände durchläuft ein Thread im Lebenszyklus:

Der Hauptthread

In C# wird die Klasse System.Threading.Thread für die Arbeit mit Threads verwendet. Sie ermöglicht das Erstellen und Zugreifen auf einzelne Threads in einer Multithreading-Anwendung. Der erste Thread, der in einem Prozess ausgeführt wird, heißt der Hauptthread.

Wenn ein C#-Programm die Ausführung startet, wird der Hauptthread automatisch erstellt. Die mit der Thread-Klasse erstellten Threads werden als Kindthreads des Hauptthreads bezeichnet. Sie können über die CurrentThread-Eigenschaft der Thread-Klasse auf einen Thread zugreifen.

Das folgende Programm demonstriert die Hauptthread-Ausführung:

using System;
using System.Threading;
namespace MultithreadingApplication {
    class MainThreadProgram {
        static void Main(string[] args) {
            Thread th = Thread.CurrentThread;
            th.Name = "MainThread";
            Console.WriteLine("This is {0}", th.Name);
            Console.ReadKey();
        }
    }
}

Wenn der obige Code kompiliert und ausgeführt wird, erzeugt er folgendes Ergebnis:

This is MainThread

Eigenschaften und Methoden der Thread-Klasse

Die folgende Tabelle zeigt einige der am häufigsten verwendeten Eigenschaften der Thread-Klasse:

Nr.Eigenschaft & Beschreibung
1

CurrentContext

Ruft den aktuellen Kontext ab, in dem der Thread ausgeführt wird.

2

CurrentCulture

Ruft die Kultur für den aktuellen Thread ab oder legt diese fest.

3

CurrentPrincipal

Ruft den aktuellen Principal des Threads ab oder legt diesen fest (für rollenbasierte Sicherheit).

4

CurrentThread

Ruft den aktuell ausgeführten Thread ab.

5

CurrentUICulture

Ruft die aktuelle Kultur ab, die vom Resource Manager verwendet wird, um kulturabhängige Ressourcen zur Laufzeit zu finden, oder legt diese fest.

6

ExecutionContext

Ruft ein ExecutionContext-Objekt ab, das Informationen zu den verschiedenen Kontexten des aktuellen Threads enthält.

7

IsAlive

Ruft einen Wert ab, der den Ausführungsstatus des aktuellen Threads angibt.

8

IsBackground

Ruft einen Wert ab, der angibt, ob ein Thread ein Hintergrundthread ist, oder legt diesen fest.

9

IsThreadPoolThread

Ruft einen Wert ab, der angibt, ob ein Thread zum verwalteten Threadpool gehört.

10

ManagedThreadId

Ruft einen eindeutigen Bezeichner für den aktuellen verwalteten Thread ab.

11

Name

Ruft den Namen des Threads ab oder legt diesen fest.

12

Priority

Ruft einen Wert ab, der die Planungspräferenz eines Threads angibt, oder legt diesen fest.

13

ThreadState

Ruft einen Wert ab, der die Zustände des aktuellen Threads enthält.

Die folgende Tabelle zeigt einige der am häufigsten verwendeten Methoden der Thread-Klasse:

Nr.Methode & Beschreibung
1

public void Abort()

Löst eine ThreadAbortException im Thread aus, auf dem sie aufgerufen wird, um den Beendigungsprozess zu beginnen. Der Aufruf dieser Methode beendet den Thread normalerweise.

2

public static LocalDataStoreSlot AllocateDataSlot()

Weist einen unbenannten Datenslot auf allen Threads zu. Für bessere Performance verwenden Sie Felder, die mit dem ThreadStaticAttribute-Attribut markiert sind.

3

public static LocalDataStoreSlot AllocateNamedDataSlot(string name)

Weist einen benannten Datenslot auf allen Threads zu. Für bessere Performance verwenden Sie Felder, die mit dem ThreadStaticAttribute-Attribut markiert sind.

4

public static void BeginCriticalRegion()

Benachrichtigt einen Host, dass die Ausführung einen Codebereich betritt, in dem die Auswirkungen eines Thread-Aborts oder einer nicht behandelten Exception andere Tasks in der Anwendungsdomäne gefährden könnten.

5

public static void BeginThreadAffinity()

Benachrichtigt einen Host, dass verwalteter Code Anweisungen ausführen wird, die von der Identität des aktuellen physischen Betriebssystem-Threads abhängen.

6

public static void EndCriticalRegion()

Benachrichtigt einen Host, dass die Ausführung einen Codebereich betritt, in dem die Auswirkungen eines Thread-Aborts oder einer nicht behandelten Exception auf den aktuellen Task beschränkt sind.

7

public static void EndThreadAffinity()

Benachrichtigt einen Host, dass verwalteter Code die Ausführung von Anweisungen beendet hat, die von der Identität des aktuellen physischen Betriebssystem-Threads abhängen.

8

public static void FreeNamedDataSlot(string name)

Entfernt die Verknüpfung zwischen einem Namen und einem Slot für alle Threads im Prozess. Für bessere Performance verwenden Sie Felder, die mit dem ThreadStaticAttribute-Attribut markiert sind.

9

public static Object GetData(LocalDataStoreSlot slot)

Ruft den Wert aus dem angegebenen Slot im aktuellen Thread innerhalb der aktuellen Thread-Domäne ab. Für bessere Performance verwenden Sie Felder, die mit dem ThreadStaticAttribute-Attribut markiert sind.

10

public static AppDomain GetDomain()

Gibt die aktuelle Domäne zurück, in der der aktuelle Thread ausgeführt wird.

11

public static AppDomain GetDomainID()

Gibt einen eindeutigen Anwendungsdomänen-Bezeichner zurück.

12

public static LocalDataStoreSlot GetNamedDataSlot(string name)

Sucht einen benannten Datenslot. Für bessere Performance verwenden Sie Felder, die mit dem ThreadStaticAttribute-Attribut markiert sind.

13

public void Interrupt()

Unterbricht einen Thread, der sich im WaitSleepJoin-Thread-Zustand befindet.

14

public void Join()

Blockiert den aufrufenden Thread, bis ein Thread beendet wird, während weiterhin standardmäßiges COM- und SendMessage-Pumping durchgeführt wird. Diese Methode hat verschiedene überladene Formen.

15

public static void MemoryBarrier()

Synchronisiert den Speicherzugriff: Der Prozessor, der den aktuellen Thread ausführt, kann Anweisungen nicht so umsortieren, dass Speicherzugriffe vor dem Aufruf von MemoryBarrier nach Speicherzugriffen ausgeführt werden, die dem Aufruf folgen.

16

public static void ResetAbort()

Bricht einen für den aktuellen Thread angeforderten Abort ab.

17

public static void SetData(LocalDataStoreSlot slot, Object data)

Legt die Daten im angegebenen Slot im aktuell ausgeführten Thread für die Domäne dieses Threads fest. Für bessere Performance verwenden Sie Felder, die mit dem ThreadStaticAttribute-Attribut markiert sind.

18

public void Start()

Startet einen Thread.

19

public static void Sleep(int millisecondsTimeout)

Lässt den Thread für einen bestimmten Zeitraum pausieren.

20

public static void SpinWait(int iterations)

Veranlasst einen Thread, so oft zu warten, wie durch den Iterationsparameter definiert.

21

public static byte VolatileRead(ref byte address) ...

Liest den Wert eines Felds. Der Wert ist der letzte, der von einem Prozessor im Computer geschrieben wurde, unabhängig von der Anzahl der Prozessoren oder dem Zustand des Prozessorcaches. Diese Methode hat verschiedene überladene Formen.

22

public static void VolatileWrite(ref byte address, byte value) ...

Schreibt einen Wert sofort in ein Feld, sodass der Wert für alle Prozessoren im Computer sichtbar ist. Diese Methode hat verschiedene überladene Formen.

23

public static bool Yield()

Veranlasst den aufrufenden Thread, die Ausführung an einen anderen Thread abzugeben, der auf dem aktuellen Prozessor bereit zur Ausführung ist. Das Betriebssystem wählt den Thread aus, dem zugewiesen wird.

Threads erstellen

Threads werden durch Erweitern der Thread-Klasse erstellt. Die erweiterte Thread-Klasse ruft dann die Start()-Methode auf, um die Ausführung des Kindthreads zu beginnen.

Das folgende Programm demonstriert das Konzept:

using System;
using System.Threading;
namespace MultithreadingApplication {
    class ThreadCreationProgram {
        public static void CallToChildThread() {
            Console.WriteLine("Child thread starts");
        }
        static void Main(string[] args) {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            Console.ReadKey();
        }
    }
}

Wenn der obige Code kompiliert und ausgeführt wird, erzeugt er folgendes Ergebnis:

In Main: Creating the Child thread
Child thread starts

Threads verwalten

Die Thread-Klasse stellt verschiedene Methoden zur Verwaltung von Threads bereit.

Das folgende Beispiel demonstriert die Verwendung der Sleep()-Methode, um einen Thread für einen bestimmten Zeitraum anzuhalten:

using System;
using System.Threading;
namespace MultithreadingApplication {
    class ThreadCreationProgram {
        public static void CallToChildThread() {
            Console.WriteLine("Child thread starts");
            // Thread für 5000 Millisekunden pausieren
            int sleepfor = 5000;
            Console.WriteLine("Child Thread Paused for {0} seconds", sleepfor / 1000);
            Thread.Sleep(sleepfor);
            Console.WriteLine("Child thread resumes");
        }
        static void Main(string[] args) {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            Console.ReadKey();
        }
    }
}

Wenn der obige Code kompiliert und ausgeführt wird, erzeugt er folgendes Ergebnis:

In Main: Creating the Child thread
Child thread starts
Child Thread Paused for 5 seconds
Child thread resumes

Threads beenden

Die Abort()-Methode wird verwendet, um Threads zu beenden.

Die Laufzeit bricht den Thread ab, indem sie eine ThreadAbortException auslöst. Diese Exception kann nicht abgefangen werden; die Kontrolle wird an den finally-Block übergeben, falls vorhanden.

Das folgende Programm veranschaulicht dies:

using System;
using System.Threading;
namespace MultithreadingApplication {
    class ThreadCreationProgram {
        public static void CallToChildThread() {
            try {
                Console.WriteLine("Child thread starts");
                // Etwas Arbeit verrichten, z. B. bis 10 zählen
                for (int counter = 0; counter <= 10; counter++) {
                    Thread.Sleep(500);
                    Console.WriteLine(counter);
                }
                Console.WriteLine("Child Thread Completed");
            } catch (ThreadAbortException e) {
                Console.WriteLine("Thread Abort Exception");
            } finally {
                Console.WriteLine("Couldn't catch the Thread Exception");
            }
        }
        static void Main(string[] args) {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            // Hauptthread für einige Zeit anhalten
            Thread.Sleep(2000);
            // Jetzt Child abbrechen
            Console.WriteLine("In Main: Aborting the Child thread");
            childThread.Abort();
            Console.ReadKey();
        }
    }
}

Wenn der obige Code kompiliert und ausgeführt wird, erzeugt er folgendes Ergebnis:

In Main: Creating the Child thread
Child thread starts
0
1
2
In Main: Aborting the Child thread
Thread Abort Exception
Couldn't catch the Thread Exception

C Sprache

  1. Kern- vs. Außendurchmesser bei Schraubengewinden: Die richtige Schraubengröße wählen
  2. Nähgarn: Typen, Geschichte, Produktion und Qualitätskontrolle
  3. Thread vs. ZigBee: Technischer Vergleich für IoT-Ingenieure
  4. Die richtige Gewindebehandlung wählen: Zuverlässigkeit erhöhen und Stillstandszeiten reduzieren
  5. C++ Multithreading meistern: Effiziente nebenläufige Programmierung mit POSIX Threads
  6. Python Multithreading: Effiziente Nebenläufigkeitstechniken
  7. Edge Computing erhält klaren, industrie-approbierten Rahmen
  8. Schnelle rückseitige Beleuchtung: Erfassung von über 1 Million Bilder pro Sekunde
  9. Den digitalen Faden entwirren: Siemens PLMs Blueprint für Smart Manufacturing
  10. Fadenschneider: Typen, Verwendung & Anwendungen