建立執行緒,並在啟動期間傳遞資料
建立作業系統處理序時,作業系統會插入執行緒以在該處理序中執行程式碼,包括任何原始的應用程式定義域。 從那時起,不一定要建立或終結任何作業系統執行緒,就能建立和終結應用程式定義域。 如果正在執行的程式碼為受控碼,則可藉由擷取類型 Thread 的靜態 CurrentThread 屬性,來取得正在目前應用程式定義域中執行之執行緒的 Thread 物件。 本主題說明執行緒的建立,並討論將資料傳遞至執行緒程序的替代方案。
建立執行緒
建立新的 Thread 物件,會建立新的受控執行緒。 Thread 類別具有採用 ThreadStart 委派或 ParameterizedThreadStart 委派的建構函式;委派會包裝當您呼叫 Start 方法時新執行緒所叫用的方法。 呼叫 Start 超過一次,就會擲回 ThreadStateException。
Start 方法會立即傳回,通常會在實際啟動新的執行緒之前。 您隨時都可使用 ThreadState 和 IsAlive 屬性來判斷執行緒的狀態,但不應使用這些屬性來進行執行緒活動的同步處理。
注意
一旦啟動執行緒之後,就不需要保留對 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()
{
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();
}
// The example displays output like the following:
// The Main() thread calls this after starting the new InstanceCaller thread.
// The Main() thread calls this after starting the new StaticCaller thread.
// ServerClass.StaticMethod is running on another thread.
// ServerClass.InstanceMethod is running on another thread.
// The instance method called by the worker thread has ended.
// The static method called by the worker thread has ended.
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()
{
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.");
}
}
// The example displays the output like the following:
// The Main() thread calls this after starting the new InstanceCaller thread.
// The Main() thread calls this after starting the new StaticCaller thread.
// ServerClass.StaticMethod is running on another thread.
// ServerClass.InstanceMethod is running on another thread.
// The instance method called by the worker thread has ended.
// The static method called by the worker thread has ended.
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()
Dim serverObject As New ServerClass()
' Create the thread object, passing in the
' serverObject.InstanceMethod method using a
' ThreadStart delegate.
Dim InstanceCaller As New Thread(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
' The example displays output like the following:
' The Main() thread calls this after starting the new InstanceCaller thread.
' The Main() thread calls this after starting the new StaticCaller thread.
' ServerClass.StaticMethod is running on another thread.
' ServerClass.InstanceMethod is running on another thread.
' The instance method called by the worker thread has ended.
' The static method called by the worker thread has ended.
將資料傳遞到執行緒
ParameterizedThreadStart 委派提供一個簡易的方式,在您呼叫 Thread.Start(Object) 時,將包含資料的物件傳遞至執行緒。 請參閱 ParameterizedThreadStart,以取得程式碼範例。
使用 ParameterizedThreadStart 委派並非傳遞資料的型別安全方式,因為 Thread.Start(Object) 方法接受任何物件。 替代方法是在協助程式類別中封裝執行緒程序和資料,並使用 ThreadStart 委派來執行執行緒程序。 下列範例展示此技術:
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 numberValue;
// The constructor obtains the state information.
public:
ThreadWithState(String^ text, int number)
{
boilerplate = text;
numberValue = number;
}
// The thread procedure performs the task, such as formatting
// and printing a document.
void ThreadProc()
{
Console::WriteLine(boilerplate, numberValue);
}
};
// 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();
}
// This example displays the following output:
// Main thread does some work, then waits.
// This report displays the number 42.
// Independent task has completed; main thread ends.
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 numberValue;
// The constructor obtains the state information.
public ThreadWithState(string text, int number)
{
boilerplate = text;
numberValue = number;
}
// The thread procedure performs the task, such as formatting
// and printing a document.
public void ThreadProc()
{
Console.WriteLine(boilerplate, numberValue);
}
}
// 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.");
}
}
// The example displays the following output:
// Main thread does some work, then waits.
// This report displays the number 42.
// Independent task has completed; main thread ends.
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 numberValue As Integer
' The constructor obtains the state information.
Public Sub New(text As String, number As Integer)
boilerplate = text
numberValue = number
End Sub
' The thread procedure performs the task, such as formatting
' and printing a document.
Public Sub ThreadProc()
Console.WriteLine(boilerplate, numberValue)
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 {0}.", 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
' The example displays the following output:
' Main thread does some work, then waits.
' This report displays the number 42.
' Independent task has completed; main thread ends.
因為沒有地方可從非同步呼叫傳回資料,所以 ThreadStart 或 ParameterizedThreadStart 委派都沒有傳回值。 若要擷取執行緒方法的結果,可使用回呼方法,如下一節所示。
使用回呼方法從執行緒擷取資料
下列範例示範從執行緒擷取資料的回呼方法。 包含資料和執行緒方法之類別的建構函式也會接受代表回呼方法的委派;在執行緒方法結束之前,它會叫用回呼委派。
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 numberValue;
// 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;
numberValue = 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, numberValue);
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();
}
// The example displays the following output:
// Main thread does some work, then waits.
// This report displays the number 42.
// Independent task printed 1 lines.
// Independent task has completed; main thread ends.
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 numberValue;
// 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;
numberValue = 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, numberValue);
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);
}
}
// The example displays the following output:
// Main thread does some work, then waits.
// This report displays the number 42.
// Independent task printed 1 lines.
// Independent task has completed; main thread ends.
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 numberValue 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
numberValue = 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, numberValue)
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)
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, _
AddressOf ResultCallback)
Dim t As New Thread(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
Public Shared Sub ResultCallback(lineCount As Integer)
Console.WriteLine( _
"Independent task printed {0} lines.", lineCount)
End Sub
End Class
' The example displays the following output:
' Main thread does some work, then waits.
' This report displays the number 42.
' Independent task printed 1 lines.
' Independent task has completed; main thread ends.