Die Anleitung zu C# Multithreading Programmierung
1. Der Begriff von Multithreading
Multi Thread ist ein wichtiger Begriff in der Programmiersprache und so ist die C#. Das ist die Weise der Erstellung der parallelen Thread. Sehen Sie bitte ein folgendes Beispiel um mehr zu verstehen:
HelloThread.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MultithreadingTutorial
{
class HelloThread
{
public static void Main(string[] args)
{
Console.WriteLine("Create new Thread...\n");
// Ein Sub-Thread erstellen um parallel mit dem Haupt-Thread (main thread) zu laufen.
Thread newThread = new Thread(WriteB);
Console.WriteLine("Start newThread...\n");
// Das Laufen vom newThread aktivieren
newThread.Start();
Console.WriteLine("Call Write('-') in main Thread...\n");
// Im Haupt-Thread schreiben die Zeichen '-'
for (int i = 0; i < 50; i++)
{
Console.Write('-');
// 70 milisekunde schlafen (sleep).
Thread.Sleep(70);
}
Console.WriteLine("Main Thread finished!\n");
Console.Read();
}
public static void WriteB()
{
// Die 100 Mal Schleife schreibt das Zeichen 'B' auf
for (int i = 0; i < 100; i++)
{
Console.Write('B');
// 100 milisekunde schlafen
Thread.Sleep(100);
}
}
}
}
Und dann starten Sie die Klasse
Das Arbeitsprinzip des Thread wird im folgenden Beispiel erläutert:
2. Den Parameter ins Thread übertragen
Im obenen Part haben Sie mit dem Beispiel über HelloThread kennengelernt. Sie erstellten ein Objekt, das eine static Methode einpackt um diese Methode gleichzeitig mit dem Vater Thread durchzuführen
Die static Methode kann einen Parameter zur Übertragung in dem Constructor der Klasse Thread werden wenn die Methode keinen Parameter oder einen einzigen Parameter Objekt hat.
// Eine static Methode, keinen Parameter.
public static void LetGo()
{
// ...
}
// Die static Method hat einen einzigen Parameter und das Typ von Objekt
public static void GetGo(object value)
{
// ...
}
Im nächsten Beispiel erstelle ich ein Thread, der eine static Methode mit einen Parameter (Objekt typ) einpackt. Ich laufe das Thread und übertrage die Wert für den Parameter .
MyWork.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MultithreadingTutorial
{
class MyWork
{
public static void DoWork(object ch)
{
for (int i = 0; i < 100; i++)
{
Console.Write(ch);
// 50 milisekunde schlafen
Thread.Sleep(50);
}
}
}
}
ThreadParamDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MultithreadingTutorial
{
class ThreadParamDemo
{
public static void Main(string[] args)
{
Console.WriteLine("Create new thread.. \n");
// Ein Objekt Thread packend (wrap) die statice Methode MyWork.DoWork erstellen
Thread workThread = new Thread(MyWork.DoWork);
Console.WriteLine("Start workThread...\n");
// workThread laufen und in dem Parameter für die Methode MyWork.DoWork übertragen.
workThread.Start("*");
for (int i = 0; i < 20; i++)
{
Console.Write(".");
// 30 Sekunde schlafen
Thread.Sleep(30);
}
Console.WriteLine("MainThread ends");
Console.Read();
}
}
}
Die Klasse ThreadParamDemo:starten
3. Thread benutzt die nicht-static Methode
Sie können auch einen Thread durch die Benutzung der normalen Methoden. Sehen Sie das Beispiel:
Worker.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MultithreadingTutorial
{
class Worker
{
private string name;
private int loop;
public Worker(string name, int loop)
{
this.name = name;
this.loop = loop;
}
public void DoWork(object value)
{
for (int i = 0; i < loop; i++)
{
Console.WriteLine(name + " working " + value);
Thread.Sleep(50);
}
}
}
}
WorkerTest.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MultithreadingTutorial
{
class WorkerTest
{
public static void Main(string[] args)
{
Worker w1 = new Worker("Tom",10);
// Das Objekt Thread erstellen.
Thread workerThread1 = new Thread(w1.DoWork);
// Den Parameter in die Methode DoWork übertragen.
workerThread1.Start("A");
Worker w2 = new Worker("Jerry",15);
// Das Objekt Thread erstellen.
Thread workerThread2 = new Thread(w2.DoWork);
// Den Parameter in die Methode DoWork übertragen.
workerThread2.Start("B");
Console.Read();
}
}
}
Das Beispiel durchführen:
Tom working A
Jerry working B
Jerry working B
Tom working A
Tom working A
Jerry working B
Tom working A
Jerry working B
Tom working A
Jerry working B
Tom working A
Jerry working B
Tom working A
Jerry working B
Jerry working B
Tom working A
Tom working A
Jerry working B
Jerry working B
Tom working A
Jerry working B
Jerry working B
Jerry working B
Jerry working B
Jerry working B
4. ThreadStart Delegate
ThreadStart ist eine Beauftragungsklasse (Delegate), sie wird durch die Einpackung einer Methode erstellt. Und sie wird wie ein Parameter zur Erstellung eines Objekt Thread übertragen
Um einen Thread im .Net < 2.0 zu starten, sollen Sie ein ThreadStart erstellen. Das ist eine delegate.
Ab der Version 2.0 von .NET Framework ist es nicht notwendig, ein ThreadStart klar zu erstellen. Sie brauchen nur den Namen der Methode im Constructor des Thread bestimmen
Programmer.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MultithreadingTutorial
{
class Programmer
{
private string name;
public Programmer(string name)
{
this.name= name;
}
// Das ist eine unstatic Methode, die keinen Parameter hat
public void DoCode()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine(name + " coding ... ");
Thread.Sleep(50);
}
}
}
}
ThreadStartDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MultithreadingTutorial
{
class ThreadStartDemo
{
public static void Main(string[] args)
{
// Das Objekt ThreadStart packend eine static Methode erstellen
// (Es kann die Methode ohne Parameter packen
// (Es ist das Objekt zur Durchführung der Methode).
ThreadStart threadStart1 = new ThreadStart(DoWork);
// Ein Thread packend (wrap) threadStart1 erstellen.
Thread workThread = new Thread(threadStart1);
// Die Aufruf auf start thread
workThread.Start();
// Ein Objekt Programmer initializieren
Programmer tran = new Programmer("Tran");
// Sie können das Objekt ThreadStart erstellen um die statice Methode einzupacken .
// (ThreadStart kann die Methode ohne Parameter einpacken)
ThreadStart threadStart2 = new ThreadStart(tran.DoCode);
// Ein Thread packend threadStart2 erstellen.
Thread progThread = new Thread(threadStart2);
progThread.Start();
Console.WriteLine("Main thread ends");
Console.Read();
}
public static void DoWork()
{
for (int i = 0; i < 10; i++)
{
Console.Write("*");
Thread.Sleep(100);
}
}
}
}
Das Beispeil durchführen:
Main thread ends
*Tran coding ...
Tran coding ...
Tran coding ...
*Tran coding ...
*Tran coding ...
*******
5. Thread mit den anonymen Kode
Im den obengenannten Part haben Sie die Thread durch die Benutzung einer bestimmten Methode erstellt. Sie können einen Thread erstellen um irgendeine Code zu implementieren.
// delegate() benutzen um eine anonyme Methode zu erstellen
delegate()
{
// ...
}
Zum Beispiel
ThreadUsingSnippetCode.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MultithreadingTutorial
{
class ThreadUsingSnippetCode
{
public static void Main(string[] args)
{
Console.WriteLine("Create thread 1");
// Ein Thread erstellen um eine Code durchzuführen
Thread newThread1 = new Thread(
delegate()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Code in delegate() " + i);
Thread.Sleep(50);
}
}
);
Console.WriteLine("Start newThread1");
// Start thread.
newThread1.Start();
Console.WriteLine("Create thread 2");
// Ein Thread erstellen um eine Code durchzuführen.
Thread newThread2 = new Thread(
delegate(object value)
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Code in delegate(object) " + i + " - " + value);
Thread.Sleep(100);
}
}
);
Console.WriteLine("Start newThread2");
// Thread 2 beginnen
// Die Wert für delegate() übertragen.
newThread2.Start("!!!");
Console.WriteLine("Main thread ends");
Console.Read();
}
}
}
Das Beispiel durchführen
Create thread 1
Start newThread1
Create thread 2
Start newThread2
Main thread ends
Code in delegate() 0
Code in delegate(object) 0 - !!!
Code in delegate() 1
Code in delegate() 2
Code in delegate(object) 1 - !!!
Code in delegate() 3
Code in delegate(object) 2 - !!!
Code in delegate() 4
Code in delegate() 5
Code in delegate(object) 3 - !!!
Code in delegate() 6
Code in delegate() 7
Code in delegate(object) 4 - !!!
Code in delegate() 8
Code in delegate() 9
Code in delegate(object) 5 - !!!
Code in delegate(object) 6 - !!!
Code in delegate(object) 7 - !!!
Code in delegate(object) 8 - !!!
Code in delegate(object) 9 - !!!
6. Den Name für Thread stellen
In der Programmierung des MultiThread können Sie automatisch den Name für den Thread stellen. Es ist wirklich nützlich beim Debugging. Damit können wir kennen, die Code wird in welchem Thread implementiert.
In einem Thread können Sie Thread.CurrentThread.Name aufrufen um den Name des implementierenden Thread zu haben
Sehen Sie das Beispiel
In einem Thread können Sie Thread.CurrentThread.Name aufrufen um den Name des implementierenden Thread zu haben
Sehen Sie das Beispiel
NamingThreadDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MultithreadingTutorial
{
class NamingThreadDemo
{
public static void Main(string[] args)
{
// Den Name für das aktuelle Thread stellen (Das Hauptthread)
Thread.CurrentThread.Name = "Main";
Console.WriteLine("Code of "+ Thread.CurrentThread.Name);
Console.WriteLine("Create new thread");
// Ein Thread erstellen.
Thread letgoThread = new Thread(LetGo);
// Den Name für das Thread stellen
letgoThread.Name = "Let's Go";
letgoThread.Start();
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Code of " + Thread.CurrentThread.Name);
Thread.Sleep(30);
}
Console.Read();
}
public static void LetGo()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Code of " + Thread.CurrentThread.Name);
Thread.Sleep(50);
}
}
}
}
Das Beispiel durchführen
Code of Main
Create new thread
Code of Main
Code of Let's Go
Code of Main
Code of Let's Go
Code of Main
Code of Main
Code of Main
Code of Let's Go
Code of Let's Go
Code of Let's Go
Code of Let's Go
Code of Let's Go
Code of Let's Go
Code of Let's Go
Code of Let's Go
7. Die Priorität zwischen Thread
Im C# gibt es 5 Prioritätlevel eines Thread. Sie werden in enum ThreadPriority.definiert
** ThreadPriority enum **
enum ThreadPriority {
Lowest,
BelowNormal,
Normal,
AboveNormal,
Highest
}
Normalerweise ist es Ihnen beim der highspeed Computer schwierig, den Unterschied zwischen der hochprioritäten Thread und der wenigprioritäten Thread zu sehen wenn die Thread wenige Arbeit machen.
Das folgende BEispiel hat 2 Thread. Jeder Thread drückt 100K Textzeile aus. (Eine genug große Menge zeigt den Unterschied).
Das folgende BEispiel hat 2 Thread. Jeder Thread drückt 100K Textzeile aus. (Eine genug große Menge zeigt den Unterschied).
ThreadPriorityDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MultithreadingTutorial
{
class ThreadPriorityDemo
{
private static DateTime endsDateTime1;
private static DateTime endsDateTime2;
public static void Main(string[] args)
{
endsDateTime1 = DateTime.Now;
endsDateTime2 = DateTime.Now;
Thread thread1 = new Thread(Hello1);
// Die höchste Priorität für thread1 stellen
thread1.Priority = ThreadPriority.Highest;
Thread thread2 = new Thread(Hello2);
// Die niedrigste Prioriät für thread2 stellen
thread2.Priority = ThreadPriority.Lowest;
thread2.Start(); thread1.Start();
Console.Read();
}
public static void Hello1()
{
for (int i = 0; i < 100000; i++)
{
Console.WriteLine("Hello from thread 1: "+ i);
}
// Die Zeit der Ende des thread1 .
endsDateTime1 = DateTime.Now;
PrintInterval();
}
public static void Hello2()
{
for (int i = 0; i < 100000; i++)
{
Console.WriteLine("Hello from thread 2: "+ i);
}
// Die Zeit der Ende des thread2 .
endsDateTime2 = DateTime.Now;
PrintInterval();
}
private static void PrintInterval()
{
// Der Zeitraum (Milisekunde)
TimeSpan interval = endsDateTime2 - endsDateTime1;
Console.WriteLine("Thread2 - Thread1 = " + interval.TotalMilliseconds + " milliseconds");
}
}
}
Das Beispiel durchführen
8. Join() benutzen
Thread.Join() ist eine Methode zu informieren, dass wart auf die Erledigung eines Thread und dann der VaterThread weiter läuft.
ThreadJoinDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MultithreadingTutorial
{
class ThreadJoinDemo
{
public static void Main(string[] args)
{
Console.WriteLine("Create new thread");
Thread letgoThread = new Thread(LetGo);
// Ein Thread beginnen (start thread).
letgoThread.Start();
// Mit dem VaterThread sagen (hier ist das Main Thread)
// Warten auf die Erledigung vom letgoThread und dann laufen weiter.
letgoThread.Join();
// Die Code wartet auf die Erledigung von letgoThread und dann läuft weiter
Console.WriteLine("Main thread ends");
Console.Read();
}
public static void LetGo()
{
for (int i = 0; i < 15; i++)
{
Console.WriteLine("Let's Go " + i);
}
}
}
}
Das Beispiel durchführen
Create new thread
Let's Go 0
Let's Go 1
Let's Go 2
Let's Go 3
Let's Go 4
Let's Go 5
Let's Go 6
Let's Go 7
Let's Go 8
Let's Go 9
Let's Go 10
Let's Go 11
Let's Go 12
Let's Go 13
Let's Go 14
Main thread ends
9. Yield() benutzen
Theoretisch bedeutet "Yield" Übergabe, Verlassung, Kapitulation. Ein Thread Yield sagt dem Betriebssystem, dass er lasst die anderen Thread in seiner Postion liegen. Das zeigt, dass er ist nicht etwas wichtig. Beachten Sie, dass er ist nur eine Vorschlage, obwohl er ist nicht sicher, auf alles zu wirken
Deshalb wird die Methode Yield() benutzt wenn er ist nicht beschäftig, er muss etwas nicht wichtig machen so er schlägt vor, dass das Betriebssystem vorläufig die Priorität für anderen Thread gibt.
Das folgende Beispiel, Es gibt 2 Thread, jeder Thread drückt 100K Textzeile ( genug groß sein, den Unterschied zu zeigen). Ein Thread ist höchstpriorität und ein kleinstpriorität. Wir messen die Zeit zum Stoppen des 2 Thread.
ThreadYieldDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MultithreadingTutorial
{
class ThreadYieldDemo
{
private static DateTime importantEndTime;
private static DateTime unImportantEndTime;
public static void Main(string[] args)
{
importantEndTime = DateTime.Now;
unImportantEndTime = DateTime.Now;
Console.WriteLine("Create thread 1");
Thread importantThread = new Thread(ImportantWork);
// Die höchste Priorität für das Thread stellen.
importantThread.Priority = ThreadPriority.Highest;
Console.WriteLine("Create thread 2");
Thread unImportantThread = new Thread(UnImportantWork);
// Die niedrigste Priorität für das Thread stellen
unImportantThread.Priority = ThreadPriority.Lowest;
// Start threads.
unImportantThread.Start();
importantThread.Start();
Console.Read();
}
// Eine wichtige Dinge fordert die hohe Priorität an.
public static void ImportantWork()
{
for (int i = 0; i < 100000; i++)
{
Console.WriteLine("\n Important work " + i);
// Dem Betriebssystem informieren, das Thread gibt die Priorität für das andere Thread
Thread.Yield();
}
// Die Zeitpunkt des Ende des thread.
importantEndTime = DateTime.Now;
PrintTime();
}
public static void UnImportantWork()
{
for (int i = 0; i < 100000; i++)
{
Console.WriteLine("\n -- UnImportant work " + i);
}
// Die Zeitpunkt des Ende des thread.
unImportantEndTime = DateTime.Now;
PrintTime();
}
private static void PrintTime()
{
// Die Zeitraum (Milisekunde)
TimeSpan interval = unImportantEndTime - importantEndTime;
Console.WriteLine("UnImportant Thread - Important Thread = " + interval.TotalMilliseconds +" milliseconds");
}
}
}
Starten Sie die oben Klasse ohne Thread.Yield():
Starten Sie die oben Klasse falls der höherpriorität Thread ununterbrochen auf Thread.Yield() aufruft um anzufordern, dass das System vorläufig die Priorität für die anderen Thread gibt.
Anleitungen C#
- Vererbung und Polymorphismus in C#
- Was ist erforderlich, um mit C# zu beginnen?
- Schnelles Lernen C# für Anfänger
- Installieren Sie Visual Studio 2013 unter Windows
- Abstrakte Klasse und Schnittstelle in C#
- Installieren Sie Visual Studio 2015 unter Windows
- Kompression und Dekompression in C#
- Die Anleitung zu C# Multithreading Programmierung
- Die Anleitung zu C# Delegate und Event
- Installieren Sie AnkhSVN unter Windows
- C# Programmierung für Team mit Visual Studio und SVN
- Installieren Sie .Net Framework
- Zugriffsmodifikator (Access Modifier) in C#
- Die Anleitung zu C# String und StringBuilder
- Die Anleitung zu C# Property
- Die Anleitung zu C# Enum
- Die Anleitung zu C# Structure
- Die Anleitung zu C# Generics
- Ausnahmen und Ausnahmebehandlung in C#
- Die Anleitung zu C# Date Time
- Manipulieren von Dateien und Verzeichnissen in C#
- Die Anleitung zu C# Stream - binäre Ströme in C#
- Die Anleitung zu C# Reguläre Ausdrücke
- Stellen Sie in C# eine Verbindung zur SQL Server-Datenbank her
- Arbeiten Sie mit der SQL Server-Datenbank in C#
- Stellen Sie in C# eine Verbindung zur MySQL-Datenbank her
- Arbeiten Sie mit der MySQL-Datenbank in C#
- Stellen Sie ohne Oracle Client eine Verbindung zur Oracle-Datenbank in C# her
- Arbeiten Sie mit der Oracle-Datenbank in C#
Show More