Erstellen von Threads und Übergeben von Daten zur Startzeit
Beim Erstellen eines Prozesses im Betriebssystem wird ein Thread eingeschleust, um Code in diesem Prozess auszuführen, einschließlich jeder ursprünglichen Anwendungsdomäne. Ab diesem Zeitpunkt können Anwendungsdomänen erstellt und gelöscht werden, ohne dass Betriebssystemthreads erstellt oder gelöscht werden müssen. Bei verwaltetem ausgeführtem Code kann ein Thread-Objekt für den in der aktuellen Anwendungsdomäne ausführenden Thread abgerufen werden. Dies erfolgt durch Abruf der statischen CurrentThread-Eigenschaft vom Typ Thread. In diesem Thema wird die Threaderstellung beschrieben, und es werden Alternativen zur Übergabe von Daten an die Threadprozedur erläutert.
Erstellen eines Threads
Beim Erstellen eines neuen Thread-Objekts wird ein neuer verwalteter Thread erstellt. Die Thread-Klasse verfügt über Konstruktoren, die einen ThreadStart-Delegaten oder einen ParameterizedThreadStart-Delegaten akzeptieren. Der Delegat umschließt die Methode, die beim Aufrufen der Start-Methode vom neuen Thread aufgerufen wird. Das mehrfache Aufrufen von Start hat zur Folge, dass ThreadStateException ausgelöst wird.
Wenn die Start-Methode zurückkehrt, befindet sich der Thread im Running-Zustand. Es ist bereit, und die Ausführung des Threads kann geplant werden, eventuell wurde die Ausführung jedoch noch nicht gestartet.
Hinweis |
---|
In den meisten Fällen ist es nicht notwendig sicherzustellen, dass der neue Thread bereits gestartet wurde, bevor der initiierende Thread, der den Thread gestartet hat, die Ausführung fortsetzt.Wenn dies erforderlich ist, sollte der Thread, der die Start-Methode aufgerufen hat, blockieren, sobald er den neuen Thread gestartet hat (z. B. durch Aufrufen der Mutex.WaitOne-Methode in einem Mutex, der im neuen Thread sichtbar ist).Der neue Thread kann die Blockierung des alten Threads aufheben (z. B. durch Aufrufen der Mutex.ReleaseMutex-Methode im gemeinsamen Mutex), sobald der alte Thread gefahrlos fortgesetzt werden kann.Verwenden Sie zum Synchronisieren der Aktivitäten von Threads nicht die ThreadState-Methode oder die IsAlive-Methode. |
Sobald ein Thread gestartet wird, ist es nicht notwendig, einen Verweis auf das Thread-Objekt beizubehalten. Der Thread wird bis zum Ende der Threadprozedur fortgesetzt.
Im folgenden Codebeispiel werden zwei neue Threads erstellt, um Instanz- und statische Methoden für ein anderes Objekt aufzurufen.
Imports System
Imports System.Threading
Public class ServerClass
' The method that will be called when the thread is started.
Public Sub InstanceMethod()
Console.WriteLine(
"ServerClass.InstanceMethod is running on another thread.")
' Pause for a moment to provide a delay to make
' threads more apparent.
Thread.Sleep(3000)
Console.WriteLine(
"The instance method called by the worker thread has ended.")
End Sub
Public Shared Sub SharedMethod()
Console.WriteLine(
"ServerClass.SharedMethod is running on another thread.")
' Pause for a moment to provide a delay to make
' threads more apparent.
Thread.Sleep(5000)
Console.WriteLine(
"The Shared method called by the worker thread has ended.")
End Sub
End Class
Public class Simple
Public Shared Sub Main()
Console.WriteLine("Thread Simple Sample")
Dim serverObject As New ServerClass()
' Create the thread object, passing in the
' serverObject.InstanceMethod method using a
' ThreadStart delegate.
Dim InstanceCaller As New Thread( _
New ThreadStart(AddressOf serverObject.InstanceMethod))
' Start the thread.
InstanceCaller.Start()
Console.WriteLine("The Main() thread calls this after " _
+ "starting the new InstanceCaller thread.")
' Create the thread object, passing in the
' serverObject.SharedMethod method using a
' ThreadStart delegate.
Dim SharedCaller As New Thread( _
New ThreadStart(AddressOf ServerClass.SharedMethod))
' Start the thread.
SharedCaller.Start()
Console.WriteLine("The Main() thread calls this after " _
+ "starting the new SharedCaller thread.")
End Sub
End Class
using System;
using System.Threading;
public class ServerClass
{
// The method that will be called when the thread is started.
public void InstanceMethod()
{
Console.WriteLine(
"ServerClass.InstanceMethod is running on another thread.");
// Pause for a moment to provide a delay to make
// threads more apparent.
Thread.Sleep(3000);
Console.WriteLine(
"The instance method called by the worker thread has ended.");
}
public static void StaticMethod()
{
Console.WriteLine(
"ServerClass.StaticMethod is running on another thread.");
// Pause for a moment to provide a delay to make
// threads more apparent.
Thread.Sleep(5000);
Console.WriteLine(
"The static method called by the worker thread has ended.");
}
}
public class Simple
{
public static void Main()
{
Console.WriteLine("Thread Simple Sample");
ServerClass serverObject = new ServerClass();
// Create the thread object, passing in the
// serverObject.InstanceMethod method using a
// ThreadStart delegate.
Thread InstanceCaller = new Thread(
new ThreadStart(serverObject.InstanceMethod));
// Start the thread.
InstanceCaller.Start();
Console.WriteLine("The Main() thread calls this after "
+ "starting the new InstanceCaller thread.");
// Create the thread object, passing in the
// serverObject.StaticMethod method using a
// ThreadStart delegate.
Thread StaticCaller = new Thread(
new ThreadStart(ServerClass.StaticMethod));
// Start the thread.
StaticCaller.Start();
Console.WriteLine("The Main() thread calls this after "
+ "starting the new StaticCaller thread.");
}
}
using namespace System;
using namespace System::Threading;
public ref class ServerClass
{
public:
// The method that will be called when the thread is started.
void InstanceMethod()
{
Console::WriteLine(
"ServerClass.InstanceMethod is running on another thread.");
// Pause for a moment to provide a delay to make
// threads more apparent.
Thread::Sleep(3000);
Console::WriteLine(
"The instance method called by the worker thread has ended.");
}
static void StaticMethod()
{
Console::WriteLine(
"ServerClass.StaticMethod is running on another thread.");
// Pause for a moment to provide a delay to make
// threads more apparent.
Thread::Sleep(5000);
Console::WriteLine(
"The static method called by the worker thread has ended.");
}
};
public ref class Simple
{
public:
static void Main()
{
Console::WriteLine("Thread Simple Sample");
ServerClass^ serverObject = gcnew ServerClass();
// Create the thread object, passing in the
// serverObject.InstanceMethod method using a
// ThreadStart delegate.
Thread^ InstanceCaller = gcnew Thread(
gcnew ThreadStart(serverObject, &ServerClass::InstanceMethod));
// Start the thread.
InstanceCaller->Start();
Console::WriteLine("The Main() thread calls this after "
+ "starting the new InstanceCaller thread.");
// Create the thread object, passing in the
// serverObject.StaticMethod method using a
// ThreadStart delegate.
Thread^ StaticCaller = gcnew Thread(
gcnew ThreadStart(&ServerClass::StaticMethod));
// Start the thread.
StaticCaller->Start();
Console::WriteLine("The Main() thread calls this after "
+ "starting the new StaticCaller thread.");
}
};
int main()
{
Simple::Main();
}
Übergeben von Daten an Threads und Abrufen von Daten aus Threads
In .NET Framework, Version 2.0, bietet der ParameterizedThreadStart-Delegat ein einfaches Verfahren zur Übergabe eines Objekts mit Daten an einen Thread, sobald die Überladung der Thread.Start-Methode aufgerufen wird. Ein Codebeispiel finden Sie unter ParameterizedThreadStart.
Die Verwendung des ParameterizedThreadStart-Delegaten ist kein typsicheres Verfahren zur Übergabe von Daten, da die Überladung der Thread.Start-Methode beliebige Objekte akzeptiert. Eine Alternative besteht darin, die Threadprozedur und die Daten in einer Hilfsklasse zu kapseln und die Threadprozedur mit dem ThreadStart-Delegaten auszuführen. Dieses Verfahren wird in den folgenden beiden Codebeispielen veranschaulicht.
Keiner dieser Delegaten verfügt über einen Rückgabewert, da die Rückgabe der Daten aus einem asynchronen Aufruf nicht vorgesehen ist. Um die Ergebnisse einer Threadmethode abzurufen, können Sie eine Rückrufmethode verwenden (siehe zweites Codebeispiel).
Imports System
Imports System.Threading
' The ThreadWithState class contains the information needed for
' a task, and the method that executes the task.
'
Public Class ThreadWithState
' State information used in the task.
Private boilerplate As String
Private value As Integer
' The constructor obtains the state information.
Public Sub New(text As String, number As Integer)
boilerplate = text
value = number
End Sub
' The thread procedure performs the task, such as formatting
' and printing a document.
Public Sub ThreadProc()
Console.WriteLine(boilerplate, value)
End Sub
End Class
' Entry point for the example.
'
Public Class Example
Public Shared Sub Main()
' Supply the state information required by the task.
Dim tws As New ThreadWithState( _
"This report displays the number {0End.", 42)
' Create a thread to execute the task, and then
' start the thread.
Dim t As New Thread(New ThreadStart(AddressOf tws.ThreadProc))
t.Start()
Console.WriteLine("Main thread does some work, then waits.")
t.Join()
Console.WriteLine( _
"Independent task has completed main thread ends.")
End Sub
End Class
using System;
using System.Threading;
// The ThreadWithState class contains the information needed for
// a task, and the method that executes the task.
//
public class ThreadWithState
{
// State information used in the task.
private string boilerplate;
private int value;
// The constructor obtains the state information.
public ThreadWithState(string text, int number)
{
boilerplate = text;
value = number;
}
// The thread procedure performs the task, such as formatting
// and printing a document.
public void ThreadProc()
{
Console.WriteLine(boilerplate, value);
}
}
// Entry point for the example.
//
public class Example
{
public static void Main()
{
// Supply the state information required by the task.
ThreadWithState tws = new ThreadWithState(
"This report displays the number {0}.", 42);
// Create a thread to execute the task, and then
// start the thread.
Thread t = new Thread(new ThreadStart(tws.ThreadProc));
t.Start();
Console.WriteLine("Main thread does some work, then waits.");
t.Join();
Console.WriteLine(
"Independent task has completed; main thread ends.");
}
}
using namespace System;
using namespace System::Threading;
// The ThreadWithState class contains the information needed for
// a task, and the method that executes the task.
//
public ref class ThreadWithState
{
private:
// State information used in the task.
String^ boilerplate;
int value;
// The constructor obtains the state information.
public:
ThreadWithState(String^ text, int number)
{
boilerplate = text;
value = number;
}
// The thread procedure performs the task, such as formatting
// and printing a document.
void ThreadProc()
{
Console::WriteLine(boilerplate, value);
}
};
// Entry point for the example.
//
public ref class Example
{
public:
static void Main()
{
// Supply the state information required by the task.
ThreadWithState^ tws = gcnew ThreadWithState(
"This report displays the number {0}.", 42);
// Create a thread to execute the task, and then
// start the thread.
Thread^ t = gcnew Thread(gcnew ThreadStart(tws, &ThreadWithState::ThreadProc));
t->Start();
Console::WriteLine("Main thread does some work, then waits.");
t->Join();
Console::WriteLine(
"Independent task has completed; main thread ends.");
}
};
int main()
{
Example::Main();
}
Abrufen von Daten mit Rückrufmethoden
Im folgenden Beispiel wird eine Rückrufmethode dargestellt, die Daten aus einem Thread abruft. Der Konstruktor für die Klasse, der die Daten und die Threadmethode enthält, akzeptiert auch einen Delegaten, der die Rückrufmethode darstellt. Vor dem Ende der Threadmethode ruft er den Rückrufdelegaten auf.
Imports System
Imports System.Threading
' The ThreadWithState class contains the information needed for
' a task, the method that executes the task, and a delegate
' to call when the task is complete.
'
Public Class ThreadWithState
' State information used in the task.
Private boilerplate As String
Private value As Integer
' Delegate used to execute the callback method when the
' task is complete.
Private callback As ExampleCallback
' The constructor obtains the state information and the
' callback delegate.
Public Sub New(text As String, number As Integer, _
callbackDelegate As ExampleCallback)
boilerplate = text
value = number
callback = callbackDelegate
End Sub
' The thread procedure performs the task, such as
' formatting and printing a document, and then invokes
' the callback delegate with the number of lines printed.
Public Sub ThreadProc()
Console.WriteLine(boilerplate, value)
If Not (callback Is Nothing) Then
callback(1)
End If
End Sub
End Class
' Delegate that defines the signature for the callback method.
'
Public Delegate Sub ExampleCallback(lineCount As Integer)
' Entry point for the example.
'
Public Class Example
Public Shared Sub Main()
' Supply the state information required by the task.
Dim tws As New ThreadWithState( _
"This report displays the number {0}.", _
42, _
New ExampleCallback(AddressOf ResultCallback) _
)
Dim t As New Thread(New ThreadStart(AddressOF tws.ThreadProc))
t.Start()
Console.WriteLine("Main thread does some work, then waits.")
t.Join()
Console.WriteLine( _
"Independent task has completed; main thread ends.")
End Sub
' The callback method must match the signature of the
' callback delegate.
'
Public Shared Sub ResultCallback(lineCount As Integer)
Console.WriteLine( _
"Independent task printed {0} lines.", lineCount)
End Sub
End Class
using System;
using System.Threading;
// The ThreadWithState class contains the information needed for
// a task, the method that executes the task, and a delegate
// to call when the task is complete.
//
public class ThreadWithState
{
// State information used in the task.
private string boilerplate;
private int value;
// Delegate used to execute the callback method when the
// task is complete.
private ExampleCallback callback;
// The constructor obtains the state information and the
// callback delegate.
public ThreadWithState(string text, int number,
ExampleCallback callbackDelegate)
{
boilerplate = text;
value = number;
callback = callbackDelegate;
}
// The thread procedure performs the task, such as
// formatting and printing a document, and then invokes
// the callback delegate with the number of lines printed.
public void ThreadProc()
{
Console.WriteLine(boilerplate, value);
if (callback != null)
callback(1);
}
}
// Delegate that defines the signature for the callback method.
//
public delegate void ExampleCallback(int lineCount);
// Entry point for the example.
//
public class Example
{
public static void Main()
{
// Supply the state information required by the task.
ThreadWithState tws = new ThreadWithState(
"This report displays the number {0}.",
42,
new ExampleCallback(ResultCallback)
);
Thread t = new Thread(new ThreadStart(tws.ThreadProc));
t.Start();
Console.WriteLine("Main thread does some work, then waits.");
t.Join();
Console.WriteLine(
"Independent task has completed; main thread ends.");
}
// The callback method must match the signature of the
// callback delegate.
//
public static void ResultCallback(int lineCount)
{
Console.WriteLine(
"Independent task printed {0} lines.", lineCount);
}
}
using namespace System;
using namespace System::Threading;
// Delegate that defines the signature for the callback method.
//
public delegate void ExampleCallback(int lineCount);
// The ThreadWithState class contains the information needed for
// a task, the method that executes the task, and a delegate
// to call when the task is complete.
//
public ref class ThreadWithState
{
private:
// State information used in the task.
String^ boilerplate;
int value;
// Delegate used to execute the callback method when the
// task is complete.
ExampleCallback^ callback;
public:
// The constructor obtains the state information and the
// callback delegate.
ThreadWithState(String^ text, int number,
ExampleCallback^ callbackDelegate)
{
boilerplate = text;
value = number;
callback = callbackDelegate;
}
// The thread procedure performs the task, such as
// formatting and printing a document, and then invokes
// the callback delegate with the number of lines printed.
void ThreadProc()
{
Console::WriteLine(boilerplate, value);
if (callback != nullptr)
{
callback(1);
}
}
};
// Entry point for the example.
//
public ref class Example
{
public:
static void Main()
{
// Supply the state information required by the task.
ThreadWithState^ tws = gcnew ThreadWithState(
"This report displays the number {0}.",
42,
gcnew ExampleCallback(&Example::ResultCallback)
);
Thread^ t = gcnew Thread(gcnew ThreadStart(tws, &ThreadWithState::ThreadProc));
t->Start();
Console::WriteLine("Main thread does some work, then waits.");
t->Join();
Console::WriteLine(
"Independent task has completed; main thread ends.");
}
// The callback method must match the signature of the
// callback delegate.
//
static void ResultCallback(int lineCount)
{
Console::WriteLine(
"Independent task printed {0} lines.", lineCount);
}
};
int main()
{
Example::Main();
}
Siehe auch
Referenz
Weitere Ressourcen
Verwenden von Threads und Threading
Änderungsprotokoll
Datum |
Versionsgeschichte |
Grund |
---|---|---|
Mai 2011 |
Erläutert, wann die Ausführung eines Threads gestartet wird. |
Kundenfeedback. |