System.Threading.Thread 类
本文提供了此 API 参考文档的补充说明。
该 Thread 类创建和控制线程、设置其优先级并获取其状态。
进程启动时,公共语言运行时会自动创建单个前台线程来执行应用程序代码。 除了此主前台线程之外,进程还可以创建一个或多个线程来执行与进程关联的程序代码的一部分。 这些线程可以在前台或后台执行。 此外,可以使用 ThreadPool 该类在公共语言运行时管理的工作线程上执行代码。
启动线程
通过提供表示线程在其类构造函数中执行的方法的委托来启动线程。 然后调用该方法 Start 开始执行。
Thread构造函数可以采用两种委托类型之一,具体取决于是否可以将参数传递给要执行的方法:
如果方法没有参数,则向构造函数传递 ThreadStart 委托。 它具有签名:
public delegate void ThreadStart()
Public Delegate Sub ThreadStart()
以下示例创建并启动执行该方法的
ExecuteInForeground
线程。 该方法显示有关某些线程属性的信息,然后执行一个循环,在该循环中暂停半秒并显示经过的秒数。 当线程至少执行 5 秒时,循环将结束,线程将终止执行。using System; using System.Diagnostics; using System.Threading; public class Example2 { public static void Main() { var th = new Thread(ExecuteInForeground); th.Start(); Thread.Sleep(1000); Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId); } private static void ExecuteInForeground() { var sw = Stopwatch.StartNew(); Console.WriteLine("Thread {0}: {1}, Priority {2}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState, Thread.CurrentThread.Priority); do { Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds", Thread.CurrentThread.ManagedThreadId, sw.ElapsedMilliseconds / 1000.0); Thread.Sleep(500); } while (sw.ElapsedMilliseconds <= 5000); sw.Stop(); } } // The example displays output like the following: // Thread 3: Running, Priority Normal // Thread 3: Elapsed 0.00 seconds // Thread 3: Elapsed 0.51 seconds // Main thread (1) exiting... // Thread 3: Elapsed 1.02 seconds // Thread 3: Elapsed 1.53 seconds // Thread 3: Elapsed 2.05 seconds // Thread 3: Elapsed 2.55 seconds // Thread 3: Elapsed 3.07 seconds // Thread 3: Elapsed 3.57 seconds // Thread 3: Elapsed 4.07 seconds // Thread 3: Elapsed 4.58 seconds
open System.Diagnostics open System.Threading let executeInForeground () = let sw = Stopwatch.StartNew() printfn $"Thread {Thread.CurrentThread.ManagedThreadId}: {Thread.CurrentThread.ThreadState}, Priority {Thread.CurrentThread.Priority}" while sw.ElapsedMilliseconds <= 5000 do printfn $"Thread {Thread.CurrentThread.ManagedThreadId}: Elapsed {sw.ElapsedMilliseconds / 1000L:N2} seconds" Thread.Sleep 500 sw.Stop() let th = Thread executeInForeground th.Start() Thread.Sleep 1000 printfn $"Main thread ({Thread.CurrentThread.ManagedThreadId}) exiting..." // The example displays output like the following: // Thread 3: Running, Priority Normal // Thread 3: Elapsed 0.00 seconds // Thread 3: Elapsed 0.51 seconds // Main thread (1) exiting... // Thread 3: Elapsed 1.02 seconds // Thread 3: Elapsed 1.53 seconds // Thread 3: Elapsed 2.05 seconds // Thread 3: Elapsed 2.55 seconds // Thread 3: Elapsed 3.07 seconds // Thread 3: Elapsed 3.57 seconds // Thread 3: Elapsed 4.07 seconds // Thread 3: Elapsed 4.58 seconds
Imports System.Diagnostics Imports System.Threading Module Example3 Public Sub Main() Dim th As New Thread(AddressOf ExecuteInForeground) th.Start() Thread.Sleep(1000) Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId) End Sub Private Sub ExecuteInForeground() Dim start As DateTime = DateTime.Now Dim sw As Stopwatch = Stopwatch.StartNew() Console.WriteLine("Thread {0}: {1}, Priority {2}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState, Thread.CurrentThread.Priority) Do Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds", Thread.CurrentThread.ManagedThreadId, sw.ElapsedMilliseconds / 1000) Thread.Sleep(500) Loop While sw.ElapsedMilliseconds <= 5000 sw.Stop() End Sub End Module ' The example displays output like the following: ' Thread 3: Running, Priority Normal ' Thread 3: Elapsed 0.00 seconds ' Thread 3: Elapsed 0.51 seconds ' Main thread (1) exiting... ' Thread 3: Elapsed 1.02 seconds ' Thread 3: Elapsed 1.53 seconds ' Thread 3: Elapsed 2.05 seconds ' Thread 3: Elapsed 2.55 seconds ' Thread 3: Elapsed 3.07 seconds ' Thread 3: Elapsed 3.57 seconds ' Thread 3: Elapsed 4.07 seconds ' Thread 3: Elapsed 4.58 seconds
如果方法具有参数,则向构造函数传递 ParameterizedThreadStart 委托。 它具有签名:
public delegate void ParameterizedThreadStart(object obj)
Public Delegate Sub ParameterizedThreadStart(obj As Object)
委托执行的方法随后可以强制转换(以 C#为单位)或将参数转换为适当的类型(在 Visual Basic 中)。
以下示例与上一个示例相同,只不过它调用 Thread(ParameterizedThreadStart) 构造函数。 此方法的
ExecuteInForeground
此版本具有一个参数,该参数表示要执行的循环大约毫秒数。using System; using System.Diagnostics; using System.Threading; public class Example3 { public static void Main() { var th = new Thread(ExecuteInForeground); th.Start(4500); Thread.Sleep(1000); Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId); } private static void ExecuteInForeground(Object obj) { int interval; try { interval = (int) obj; } catch (InvalidCastException) { interval = 5000; } var sw = Stopwatch.StartNew(); Console.WriteLine("Thread {0}: {1}, Priority {2}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState, Thread.CurrentThread.Priority); do { Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds", Thread.CurrentThread.ManagedThreadId, sw.ElapsedMilliseconds / 1000.0); Thread.Sleep(500); } while (sw.ElapsedMilliseconds <= interval); sw.Stop(); } } // The example displays output like the following: // Thread 3: Running, Priority Normal // Thread 3: Elapsed 0.00 seconds // Thread 3: Elapsed 0.52 seconds // Main thread (1) exiting... // Thread 3: Elapsed 1.03 seconds // Thread 3: Elapsed 1.55 seconds // Thread 3: Elapsed 2.06 seconds // Thread 3: Elapsed 2.58 seconds // Thread 3: Elapsed 3.09 seconds // Thread 3: Elapsed 3.61 seconds // Thread 3: Elapsed 4.12 seconds
open System open System.Diagnostics open System.Threading let executeInForeground obj = let interval = try unbox<int> obj with :? InvalidCastException -> 5000 let sw = Stopwatch.StartNew() printfn $"Thread {Thread.CurrentThread.ManagedThreadId}: {Thread.CurrentThread.ThreadState}, Priority {Thread.CurrentThread.Priority}" while sw.ElapsedMilliseconds <= interval do printfn $"Thread {Thread.CurrentThread.ManagedThreadId}: Elapsed {sw.ElapsedMilliseconds / 1000L:N2} seconds" Thread.Sleep 500 sw.Stop() let th = Thread(ParameterizedThreadStart executeInForeground) th.Start 4500 Thread.Sleep 1000 printfn $"Main thread ({Thread.CurrentThread.ManagedThreadId}) exiting..." // The example displays output like the following: // Thread 3: Running, Priority Normal // Thread 3: Elapsed 0.00 seconds // Thread 3: Elapsed 0.52 seconds // Main thread (1) exiting... // Thread 3: Elapsed 1.03 seconds // Thread 3: Elapsed 1.55 seconds // Thread 3: Elapsed 2.06 seconds // Thread 3: Elapsed 2.58 seconds // Thread 3: Elapsed 3.09 seconds // Thread 3: Elapsed 3.61 seconds // Thread 3: Elapsed 4.12 seconds
Imports System.Diagnostics Imports System.Threading Module Example4 Public Sub Main() Dim th As New Thread(AddressOf ExecuteInForeground) th.Start(4500) Thread.Sleep(1000) Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId) End Sub Private Sub ExecuteInForeground(obj As Object) Dim interval As Integer If IsNumeric(obj) Then interval = CInt(obj) Else interval = 5000 End If Dim start As DateTime = DateTime.Now Dim sw As Stopwatch = Stopwatch.StartNew() Console.WriteLine("Thread {0}: {1}, Priority {2}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState, Thread.CurrentThread.Priority) Do Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds", Thread.CurrentThread.ManagedThreadId, sw.ElapsedMilliseconds / 1000) Thread.Sleep(500) Loop While sw.ElapsedMilliseconds <= interval sw.Stop() End Sub End Module ' The example displays output like the following: ' Thread 3: Running, Priority Normal ' Thread 3: Elapsed 0.00 seconds ' Thread 3: Elapsed 0.52 seconds ' Main thread (1) exiting... ' Thread 3: Elapsed 1.03 seconds ' Thread 3: Elapsed 1.55 seconds ' Thread 3: Elapsed 2.06 seconds ' Thread 3: Elapsed 2.58 seconds ' Thread 3: Elapsed 3.09 seconds ' Thread 3: Elapsed 3.61 seconds ' Thread 3: Elapsed 4.12 seconds
启动线程后,无需保留对 Thread 对象的引用。 线程继续执行,直到线程过程完成。
检索 Thread 对象
可以使用静态(Shared
在 Visual Basic 中) CurrentThread 属性从线程正在执行的代码中检索对当前正在执行的线程的引用。 以下示例使用此属性 CurrentThread 显示有关主应用程序线程、另一个前台线程、后台线程和线程池线程的信息。
using System;
using System.Threading;
public class Example1
{
static Object obj = new Object();
public static void Main()
{
ThreadPool.QueueUserWorkItem(ShowThreadInformation);
var th1 = new Thread(ShowThreadInformation);
th1.Start();
var th2 = new Thread(ShowThreadInformation);
th2.IsBackground = true;
th2.Start();
Thread.Sleep(500);
ShowThreadInformation(null);
}
private static void ShowThreadInformation(Object state)
{
lock (obj) {
var th = Thread.CurrentThread;
Console.WriteLine("Managed thread #{0}: ", th.ManagedThreadId);
Console.WriteLine(" Background thread: {0}", th.IsBackground);
Console.WriteLine(" Thread pool thread: {0}", th.IsThreadPoolThread);
Console.WriteLine(" Priority: {0}", th.Priority);
Console.WriteLine(" Culture: {0}", th.CurrentCulture.Name);
Console.WriteLine(" UI culture: {0}", th.CurrentUICulture.Name);
Console.WriteLine();
}
}
}
// The example displays output like the following:
// Managed thread #6:
// Background thread: True
// Thread pool thread: False
// Priority: Normal
// Culture: en-US
// UI culture: en-US
//
// Managed thread #3:
// Background thread: True
// Thread pool thread: True
// Priority: Normal
// Culture: en-US
// UI culture: en-US
//
// Managed thread #4:
// Background thread: False
// Thread pool thread: False
// Priority: Normal
// Culture: en-US
// UI culture: en-US
//
// Managed thread #1:
// Background thread: False
// Thread pool thread: False
// Priority: Normal
// Culture: en-US
// UI culture: en-US
open System.Threading
let obj = obj ()
let showThreadInformation (state: obj) =
lock obj (fun () ->
let th = Thread.CurrentThread
printfn $"Managed thread #{th.ManagedThreadId}: "
printfn $" Background thread: {th.IsBackground}"
printfn $" Thread pool thread: {th.IsThreadPoolThread}"
printfn $" Priority: {th.Priority}"
printfn $" Culture: {th.CurrentCulture.Name}"
printfn $" UI culture: {th.CurrentUICulture.Name}"
printfn "")
ThreadPool.QueueUserWorkItem showThreadInformation |> ignore
let th1 = Thread(ParameterizedThreadStart showThreadInformation)
th1.Start()
let th2 = Thread(ParameterizedThreadStart showThreadInformation)
th2.IsBackground <- true
th2.Start()
Thread.Sleep 500
showThreadInformation ()
// The example displays output like the following:
// Managed thread #6:
// Background thread: True
// Thread pool thread: False
// Priority: Normal
// Culture: en-US
// UI culture: en-US
//
// Managed thread #3:
// Background thread: True
// Thread pool thread: True
// Priority: Normal
// Culture: en-US
// UI culture: en-US
//
// Managed thread #4:
// Background thread: False
// Thread pool thread: False
// Priority: Normal
// Culture: en-US
// UI culture: en-US
//
// Managed thread #1:
// Background thread: False
// Thread pool thread: False
// Priority: Normal
// Culture: en-US
// UI culture: en-US
Imports System.Threading
Module Example2
Private lock As New Object()
Public Sub Main()
ThreadPool.QueueUserWorkItem(AddressOf ShowThreadInformation)
Dim th1 As New Thread(AddressOf ShowThreadInformation)
th1.Start()
Dim th2 As New Thread(AddressOf ShowThreadInformation)
th2.IsBackground = True
th2.Start()
Thread.Sleep(500)
ShowThreadInformation(Nothing)
End Sub
Private Sub ShowThreadInformation(state As Object)
SyncLock lock
Dim th As Thread = Thread.CurrentThread
Console.WriteLine("Managed thread #{0}: ", th.ManagedThreadId)
Console.WriteLine(" Background thread: {0}", th.IsBackground)
Console.WriteLine(" Thread pool thread: {0}", th.IsThreadPoolThread)
Console.WriteLine(" Priority: {0}", th.Priority)
Console.WriteLine(" Culture: {0}", th.CurrentCulture.Name)
Console.WriteLine(" UI culture: {0}", th.CurrentUICulture.Name)
Console.WriteLine()
End SyncLock
End Sub
End Module
' The example displays output like the following:
' ' Managed thread #6:
' Background thread: True
' Thread pool thread: False
' Priority: Normal
' Culture: en-US
' UI culture: en-US
'
' Managed thread #3:
' Background thread: True
' Thread pool thread: True
' Priority: Normal
' Culture: en-US
' UI culture: en-US
'
' Managed thread #4:
' Background thread: False
' Thread pool thread: False
' Priority: Normal
' Culture: en-US
' UI culture: en-US
'
' Managed thread #1:
' Background thread: False
' Thread pool thread: False
' Priority: Normal
' Culture: en-US
' UI culture: en-US
前台线程和后台线程
类的 Thread 实例表示前台线程或后台线程。 后台线程与前台线程相同,但有一个例外:如果所有前台线程已终止,后台线程不会使进程保持运行。 停止所有前台线程后,运行时将停止所有后台线程并关闭。
默认情况下,以下线程在前台执行:
主应用程序线程。
通过调用 Thread 类构造函数创建的所有线程。
默认情况下,以下线程在后台执行:
线程池线程,该线程来自运行时维护的工作线程池。 可以使用该类配置线程池并计划线程池线程 ThreadPool 上的工作。
注意
基于任务的异步操作会自动在线程池线程上执行。 基于任务的异步操作使用Task和类来实现基于任务的异步模式Task<TResult>。
从非托管代码进入托管执行环境的所有线程。
可以通过随时设置 IsBackground 属性来更改在后台执行的线程。 只要应用程序正在运行,但不应阻止应用程序终止(例如监视文件系统更改或传入套接字连接)的任何操作,后台线程都很有用。
以下示例说明了前台线程和后台线程之间的差异。 它类似于“启动线程”部分中的第一个示例,只是它设置线程在启动之前在后台执行。 如输出所示,循环在执行五秒之前中断。
using System;
using System.Diagnostics;
using System.Threading;
public class Example
{
public static void Main()
{
var th = new Thread(ExecuteInForeground);
th.IsBackground = true;
th.Start();
Thread.Sleep(1000);
Console.WriteLine("Main thread ({0}) exiting...",
Thread.CurrentThread.ManagedThreadId);
}
private static void ExecuteInForeground()
{
var sw = Stopwatch.StartNew();
Console.WriteLine("Thread {0}: {1}, Priority {2}",
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.ThreadState,
Thread.CurrentThread.Priority);
do {
Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds",
Thread.CurrentThread.ManagedThreadId,
sw.ElapsedMilliseconds / 1000.0);
Thread.Sleep(500);
} while (sw.ElapsedMilliseconds <= 5000);
sw.Stop();
}
}
// The example displays output like the following:
// Thread 3: Background, Priority Normal
// Thread 3: Elapsed 0.00 seconds
// Thread 3: Elapsed 0.51 seconds
// Main thread (1) exiting...
open System.Diagnostics
open System.Threading
let executeInForeground () =
let sw = Stopwatch.StartNew()
printfn $"Thread {Thread.CurrentThread.ManagedThreadId}: {Thread.CurrentThread.ThreadState}, Priority {Thread.CurrentThread.Priority}"
while sw.ElapsedMilliseconds <= 5000 do
printfn $"Thread {Thread.CurrentThread.ManagedThreadId}: Elapsed {sw.ElapsedMilliseconds / 1000L:N2} seconds"
Thread.Sleep 500
sw.Stop()
let th = Thread executeInForeground
th.IsBackground <- true
th.Start()
Thread.Sleep 1000
printfn $"Main thread ({Thread.CurrentThread.ManagedThreadId}) exiting..."
// The example displays output like the following:
// Thread 3: Background, Priority Normal
// Thread 3: Elapsed 0.00 seconds
// Thread 3: Elapsed 0.51 seconds
// Main thread (1) exiting...
Imports System.Diagnostics
Imports System.Threading
Module Example1
Public Sub Main()
Dim th As New Thread(AddressOf ExecuteInForeground)
th.IsBackground = True
th.Start()
Thread.Sleep(1000)
Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId)
End Sub
Private Sub ExecuteInForeground()
Dim start As DateTime = DateTime.Now
Dim sw As Stopwatch = Stopwatch.StartNew()
Console.WriteLine("Thread {0}: {1}, Priority {2}",
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.ThreadState,
Thread.CurrentThread.Priority)
Do
Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds",
Thread.CurrentThread.ManagedThreadId,
sw.ElapsedMilliseconds / 1000)
Thread.Sleep(500)
Loop While sw.ElapsedMilliseconds <= 5000
sw.Stop()
End Sub
End Module
' The example displays output like the following:
' Thread 3: Background, Priority Normal
' Thread 3: Elapsed 0.00 seconds
' Thread 3: Elapsed 0.51 seconds
' Main thread (1) exiting...
区域性和线程
每个线程都有一个区域性,由 CurrentCulture 属性表示,UI 区域性由 CurrentUICulture 该属性表示。 当前区域性支持区分区域性的操作,例如分析和格式设置、字符串比较和排序,还控制线程使用的写入系统和日历。 当前 UI 区域性提供对资源文件中资源进行区分区域性的检索。
重要
与当前线程以外的任何线程一起使用时,和CurrentCultureCurrentUICulture属性无法可靠地工作。 在 .NET Framework 中,读取这些属性是可靠的,尽管为当前线程以外的线程设置这些属性不是。 在 .NET Core 上,如果线程尝试在不同的线程上读取或写入这些属性, InvalidOperationException 则会引发此事件。 建议使用 CultureInfo.CurrentCulture 和 CultureInfo.CurrentUICulture 属性来检索和设置当前区域性。
实例化新线程时,其区域性和 UI 区域性由当前系统区域性和 UI 区域性定义,而不是由创建新线程的线程的区域性和 UI 区域性定义。 例如,如果当前系统区域性为英语(美国),并且主应用程序线程的当前区域性为法语(法国),则通过从主线程调用Thread(ParameterizedThreadStart)构造函数创建的新线程的区域性为英语(美国),而不是法语(法国)。 有关详细信息,请参阅类主题的 CultureInfo “区域性和线程”部分。
重要
对于面向 .NET Framework 4.6 及更高版本的应用执行异步操作的线程,这不是事实。 在这种情况下,区域性和 UI 区域性是异步操作上下文的一部分;默认情况下,异步操作执行的线程继承启动异步操作的线程的区域性和 UI 区域性。 有关详细信息,请参阅类备注的 CultureInfo “区域性和基于任务的异步操作”部分。
可以执行以下任一操作,以确保在应用程序中执行的所有线程共享相同的区域性和 UI 区域性:
可以将表示该区域性ParameterizedThreadStart的对象传递给CultureInfo委托或ThreadPool.QueueUserWorkItem(WaitCallback, Object)方法。
对于在 .NET Framework 4.5 及更高版本上运行的应用,可以通过设置属性的值来定义要分配给应用程序域中创建的所有线程的 CultureInfo.DefaultThreadCurrentCulture 区域性和 CultureInfo.DefaultThreadCurrentUICulture UI 区域性。 请注意,这是每应用程序域设置。
有关详细信息和示例,请参阅类备注的 CultureInfo “区域性和线程”部分。
获取有关和控制线程的信息
可以检索许多属性值,这些属性值提供有关线程的信息。 在某些情况下,还可以设置这些属性值来控制线程的操作。 这些线程属性包括:
名称。 Name 是一个写一次属性,可用于标识线程。 它的默认值为
null
。一个哈希代码,可以通过调用 GetHashCode 该方法进行检索。 哈希代码可用于唯一标识线程;对于线程的生存期,其哈希代码不会与任何其他线程的值相冲突,而不考虑从中获取该值的应用程序域。
线程 ID。 只读 ManagedThreadId 属性的值由运行时分配,并唯一标识其进程中的线程。
注意
因为非托管宿主可以控制托管线程和非托管线程之间的关系,所以操作系统 ThreadId 与托管线程之间没有固定的关系。 具体而言,复杂的主机可以使用 CLR 托管 API 针对同一操作系统线程计划多个托管线程,或在不同的操作系统线程之间移动托管线程。
线程的当前状态。 在其存在期间,线程始终处于属性定义的 ThreadState 一个或多个状态。
计划优先级,由属性定义 ThreadPriority 。 虽然可以将此值设置为请求线程的优先级,但操作系统不能保证遵守此值。
只读 IsThreadPoolThread 属性,指示线程是否为线程池线程。
IsBackground 属性。 有关详细信息,请参阅 前台和后台线程 部分。
示例
以下示例演示了简单的线程处理功能。
using System;
using System.Threading;
// Simple threading scenario: Start a static method running
// on a second thread.
public class ThreadExample {
// The ThreadProc method is called when the thread starts.
// It loops ten times, writing to the console and yielding
// the rest of its time slice each time, and then ends.
public static void ThreadProc() {
for (int i = 0; i < 10; i++) {
Console.WriteLine("ThreadProc: {0}", i);
// Yield the rest of the time slice.
Thread.Sleep(0);
}
}
public static void Main() {
Console.WriteLine("Main thread: Start a second thread.");
// The constructor for the Thread class requires a ThreadStart
// delegate that represents the method to be executed on the
// thread. C# simplifies the creation of this delegate.
Thread t = new Thread(new ThreadStart(ThreadProc));
// Start ThreadProc. Note that on a uniprocessor, the new
// thread does not get any processor time until the main thread
// is preempted or yields. Uncomment the Thread.Sleep that
// follows t.Start() to see the difference.
t.Start();
//Thread.Sleep(0);
for (int i = 0; i < 4; i++) {
Console.WriteLine("Main thread: Do some work.");
Thread.Sleep(0);
}
Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends.");
t.Join();
Console.WriteLine("Main thread: ThreadProc.Join has returned. Press Enter to end program.");
Console.ReadLine();
}
}
open System.Threading
// Simple threading scenario: Start a static method running
// on a second thread.
// The ThreadProc method is called when the thread starts.
// It loops ten times, writing to the console and yielding
// the rest of its time slice each time, and then ends.
let threadProc () =
for i = 0 to 9 do
printfn $"ThreadProc: {i}"
// Yield the rest of the time slice.
Thread.Sleep 0
printfn "Main thread: Start a second thread."
// The constructor for the Thread class requires a ThreadStart
// delegate that represents the method to be executed on the
// thread. F# simplifies the creation of this delegate.
let t = Thread threadProc
// Start ThreadProc. Note that on a uniprocessor, the new
// thread does not get any processor time until the main thread
// is preempted or yields. Uncomment the Thread.Sleep that
// follows t.Start() to see the difference.
t.Start()
//Thread.Sleep 0
for _ = 0 to 3 do
printfn "Main thread: Do some work."
Thread.Sleep 0
printfn "Main thread: Call Join(), to wait until ThreadProc ends."
t.Join()
printfn "Main thread: ThreadProc.Join has returned. Press Enter to end program."
stdin.ReadLine() |> ignore
Imports System.Threading
' Simple threading scenario: Start a Shared method running
' on a second thread.
Public Class ThreadExample
' The ThreadProc method is called when the thread starts.
' It loops ten times, writing to the console and yielding
' the rest of its time slice each time, and then ends.
Public Shared Sub ThreadProc()
Dim i As Integer
For i = 0 To 9
Console.WriteLine("ThreadProc: {0}", i)
' Yield the rest of the time slice.
Thread.Sleep(0)
Next
End Sub
Public Shared Sub Main()
Console.WriteLine("Main thread: Start a second thread.")
' The constructor for the Thread class requires a ThreadStart
' delegate. The Visual Basic AddressOf operator creates this
' delegate for you.
Dim t As New Thread(AddressOf ThreadProc)
' Start ThreadProc. Note that on a uniprocessor, the new
' thread does not get any processor time until the main thread
' is preempted or yields. Uncomment the Thread.Sleep that
' follows t.Start() to see the difference.
t.Start()
'Thread.Sleep(0)
Dim i As Integer
For i = 1 To 4
Console.WriteLine("Main thread: Do some work.")
Thread.Sleep(0)
Next
Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends.")
t.Join()
Console.WriteLine("Main thread: ThreadProc.Join has returned. Press Enter to end program.")
Console.ReadLine()
End Sub
End Class
此代码生成如下所示的输出:
[VB, C++, C#]
Main thread: Start a second thread.
Main thread: Do some work.
ThreadProc: 0
Main thread: Do some work.
ThreadProc: 1
Main thread: Do some work.
ThreadProc: 2
Main thread: Do some work.
ThreadProc: 3
Main thread: Call Join(), to wait until ThreadProc ends.
ThreadProc: 4
ThreadProc: 5
ThreadProc: 6
ThreadProc: 7
ThreadProc: 8
ThreadProc: 9
Main thread: ThreadProc.Join has returned. Press Enter to end program.