建立執行緒並在啟動時間傳遞資料
更新:2011 年 5 月
當建立作業系統處理序時,作業系統會插入執行緒以在該處理序中執行程式碼,包括任何原始應用程式定義域。 從該處,可建立及終結應用程式定義域,而不一定需要建立及終結任何作業系統執行緒。 如果正在執行的是 Managed 程式碼,則可藉由擷取 Thread 型別的靜態 CurrentThread 屬性,獲得現行應用程式定義域中正在執行的執行緒之 Thread 物件。 本主題將說明執行緒的建立,並討論將資料傳遞給執行緒程序的替代方案。
建立執行緒
建立新的 Thread 物件時,新的 Managed 執行緒也會隨之建立。 Thread 類別具有會採用 ThreadStart 委派或 ParameterizedThreadStart 委派的建構函式;當您呼叫 Start 方法時,委派會包裝新執行緒所叫用的方法。 多次呼叫 Start 會擲回 ThreadStateException。
Start 方法傳回時,執行緒會處於 Running 狀態。 它已經可以排定執行,但可能尚未開始執行。
注意事項 |
---|
在大部分案例中,不一定要在啟動新執行緒的執行緒繼續執行之前,先確定新執行緒已開始執行。如有必要,只要呼叫 Start 方法的執行緒啟動新執行緒,就應該將它封鎖 (例如,藉由在會對新執行緒顯示的 Mutex 上呼叫 Mutex.WaitOne 方法)。只要舊執行緒可安全執行,新執行緒就可以解除封鎖舊執行緒 (例如在共用的 Mutex 上呼叫 Mutex.ReleaseMutex 方法)。請勿使用 ThreadState 和 IsAlive 屬性同步處理執行緒的活動。 |
一旦執行緒啟動之後,便不需要保留 Thread 物件的參考。 此執行緒會繼續執行,一直到執行緒的程序結束為止。
下列程式碼範例建立兩個新執行緒,以在另一個物件上呼叫執行個體及靜態方法。
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();
}
將資料傳遞給執行緒以及擷取來自執行緒的資料
在 .NET Framework 2.0 版中,當您呼叫 Thread.Start 方法多載時,ParameterizedThreadStart 委派可讓您輕鬆地將含有資料的物件傳遞給執行緒。 如需程式碼範例,請參閱 ParameterizedThreadStart。
使用 ParameterizedThreadStart 委派並不是傳遞資料的型別安全方式,因為 Thread.Start 方法多載會接受任何物件。 替代方案是在 Helper 類別中封裝執行緒程序和資料,並使用 ThreadStart 委派來執行執行緒程序。 下列兩個程式碼範例將會示範這項技術。
這些委派都不具有傳回值,因為沒有地方可供傳回來自非同步呼叫的資料。 若要擷取執行緒方法的結果,可以依照第二個程式碼範例所示,使用回呼 (Callback) 方法。
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();
}
使用回呼方法擷取資料
下列範例示範回呼 (Callback) 方法,它會從執行緒擷取資料。 類別的建構函式 (Constructor) 包含資料和執行緒方法,它也接受代表回呼方法的委派;在執行緒方法結束之前,它會叫用 (Invoke) 回呼委派。
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();
}
請參閱
參考
其他資源
變更記錄
日期 |
記錄 |
原因 |
---|---|---|
2011 年 5 月 |
已釐清執行緒開始執行的時機。 |
客戶回函。 |