Thread 类

定义

创建和控制线程、设置其优先级并获取其状态。

public ref class Thread sealed : System::Runtime::ConstrainedExecution::CriticalFinalizerObject
public ref class Thread sealed
public ref class Thread sealed : System::Runtime::InteropServices::_Thread
public ref class Thread sealed : System::Runtime::ConstrainedExecution::CriticalFinalizerObject, System::Runtime::InteropServices::_Thread
public sealed class Thread : System.Runtime.ConstrainedExecution.CriticalFinalizerObject
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class Thread
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
public sealed class Thread : System.Runtime.InteropServices._Thread
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
public sealed class Thread : System.Runtime.ConstrainedExecution.CriticalFinalizerObject, System.Runtime.InteropServices._Thread
type Thread = class
    inherit CriticalFinalizerObject
[<System.Runtime.InteropServices.ComVisible(true)>]
type Thread = class
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
type Thread = class
    interface _Thread
[<System.Runtime.InteropServices.ComVisible(true)>]
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
type Thread = class
    inherit CriticalFinalizerObject
    interface _Thread
Public NotInheritable Class Thread
Inherits CriticalFinalizerObject
Public NotInheritable Class Thread
Public NotInheritable Class Thread
Implements _Thread
Public NotInheritable Class Thread
Inherits CriticalFinalizerObject
Implements _Thread
继承
继承
Thread
属性
实现

示例

以下示例演示了简单的线程处理功能。

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.

注解

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 Example
    {
       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 Example
    {
       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 Example
{
   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 上的工作。

    注释

    基于任务的异步操作会自动在线程池线程上执行。 基于任务的异步作使用 TaskTask<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 属性表示的区域性和一个由 CurrentUICulture 属性表示的 UI 区域性。 当前区域性支持区分区域性的操作,例如分析和格式设置、字符串比较和排序,还控制线程使用的写入系统和日历。 当前 UI 区域性提供对资源文件中资源进行区分区域性的检索。

Important

与当前线程以外的任何线程一起使用时,和CurrentCultureCurrentUICulture属性无法可靠地工作。 如果线程尝试在不同的线程上读取或写入这些属性,则会引发 an InvalidOperationException 。 建议使用 CultureInfo.CurrentCultureCultureInfo.CurrentUICulture 属性来检索和设置当前文化环境。

实例化新线程时,其区域性和 UI 区域性由当前系统区域性和 UI 区域性定义,而不是由创建新线程的线程的区域性和 UI 区域性定义。 例如,如果当前系统区域性为英语(美国),并且主应用程序线程的当前区域性为法语(法国),则通过从主线程调用 Thread(ParameterizedThreadStart) 构造函数创建的新线程的区域性为英语(美国),而不是法语(法国)。 有关详细信息,请参阅 CultureInfo 类主题的“文化和线程”部分。

Important

对于执行面向 .NET Framework 4.6 及更高版本应用程序异步操作的线程来说,情况并非如此。 在这种情况下,区域性和 UI 区域性是异步作上下文的一部分;默认情况下,异步作执行的线程继承启动异步作的线程的区域性和 UI 区域性。 有关详细信息,请参阅 CultureInfo 类备注中的“区域性和基于任务的异步操作”一节。

可以执行以下任一操作,以确保在应用程序中执行的所有线程共享相同的区域性和 UI 区域性:

有关详细信息和示例,请参阅 CultureInfo 类的备注 “文化与线程” 部分。

获取有关和控制线程的信息

可以检索许多属性值,这些属性值提供有关线程的信息。 在某些情况下,还可以设置这些属性值来控制线程的作。 这些线程属性包括:

  • 一个名字。 Name 是一个写一次属性,可用于标识线程。 其默认值为 null

  • 一个哈希代码,可以通过调用 GetHashCode 该方法进行检索。 哈希码可用于唯一标识线程;在线程的生存期内,它的哈希码不会与任何其他线程的值发生冲突,无论值是从哪个应用程序域中获取的。

  • 线程 ID。 只读 ManagedThreadId 属性的值由运行时分配,并唯一标识其进程中的线程。

    注释

    作系统 ThreadId 与托管线程没有固定关系,因为非托管主机可以控制托管线程和非托管线程之间的关系。 具体而言,复杂的主机可以使用 CLR 托管 API 针对同一作系统线程计划多个托管线程,或在不同的作系统线程之间移动托管线程。

  • 线程的当前状态。 在其存在期间,线程始终处于属性定义的 ThreadState 一个或多个状态。

  • ThreadPriority属性定义的调度优先级。 虽然可以将此值设置为请求线程的优先级,但操作系统不能保证执行此值。

  • 只读 IsThreadPoolThread 属性,指示线程是否为线程池线程。

  • IsBackground 属性。 有关详细信息,请参阅 前台和后台线程 部分。

构造函数

名称 说明
Thread(ParameterizedThreadStart, Int32)

初始化类的新实例 Thread ,指定一个委托,该委托允许在启动线程时将对象传递给线程,并指定线程的最大堆栈大小。

Thread(ParameterizedThreadStart)

初始化类的新实例 Thread ,指定一个委托,该委托允许在启动线程时将对象传递给线程。

Thread(ThreadStart, Int32)

初始化类的新实例 Thread ,指定线程的最大堆栈大小。

Thread(ThreadStart)

初始化 Thread 类的新实例。

属性

名称 说明
ApartmentState
已过时.
已过时.

获取或设置此线程的公寓状态。

CurrentContext

获取正在执行线程的当前上下文。

CurrentCulture

获取或设置当前线程的区域性。

CurrentPrincipal

获取或设置线程的当前主体(用于基于角色的安全性)。

CurrentThread

获取当前正在运行的线程。

CurrentUICulture

获取或设置资源管理器用于在运行时查找区域性特定资源的当前区域性。

ExecutionContext

获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。

IsAlive

获取一个值,该值指示当前线程的执行状态。

IsBackground

获取或设置一个值,该值指示线程是否为后台线程。

IsThreadPoolThread

获取一个值,该值指示线程是否属于托管线程池。

ManagedThreadId

获取当前托管线程的唯一标识符。

Name

获取或设置线程的名称。

Priority

获取或设置一个值,该值指示线程的计划优先级。

ThreadState

获取一个值,该值包含当前线程的状态。

方法

名称 说明
Abort()
已过时.

在调用线程的线程中引发一个 ThreadAbortException ,以开始终止线程的过程。 调用此方法通常会终止线程。

Abort(Object)
已过时.

在调用线程的线程中引发一个 ThreadAbortException ,以开始终止线程的过程,同时提供有关线程终止的异常信息。 调用此方法通常会终止线程。

AllocateDataSlot()

在所有线程上分配未命名的数据槽。 为了获得更好的性能,请改用带有属性标记的 ThreadStaticAttribute 字段。

AllocateNamedDataSlot(String)

在所有线程上分配命名数据槽。 为了获得更好的性能,请改用带有属性标记的 ThreadStaticAttribute 字段。

BeginCriticalRegion()

通知主机执行即将进入代码区域,其中线程中止或未经处理的异常的影响可能会危及应用程序域中的其他任务。

BeginThreadAffinity()

通知主机托管代码即将执行依赖于当前物理操作系统线程标识的说明。

DisableComObjectEagerCleanup()

关闭当前线程的运行时可调用包装器(RCW)的自动清理。

EndCriticalRegion()

通知主机执行即将进入代码区域,其中线程中止或未经处理的异常的影响仅限于当前任务。

EndThreadAffinity()

通知主机托管代码已完成执行指令,这些指令依赖于当前物理操作系统线程的标识。

Equals(Object)

确定指定的对象是否等于当前对象。

(继承自 Object)
Finalize()

确保在垃圾回收器回收 Thread 对象时释放资源和其他清理操作。

FreeNamedDataSlot(String)

消除进程中所有线程的名称和槽之间的关联。 为了获得更好的性能,请改用带有属性标记的 ThreadStaticAttribute 字段。

GetApartmentState()

返回一个 ApartmentState 值,该值指示单元状态。

GetCompressedStack()
已过时.
已过时.

返回一个 CompressedStack 对象,该对象可用于捕获当前线程的堆栈。

GetCurrentProcessorId()

获取用于指示当前线程正在执行的处理器的 ID。

GetData(LocalDataStoreSlot)

从当前线程的当前域中的指定槽中检索值。 为了获得更好的性能,请改用带有属性标记的 ThreadStaticAttribute 字段。

GetDomain()

返回运行当前线程的当前域。

GetDomainID()

返回唯一的应用程序域标识符。

GetHashCode()

返回当前线程的哈希代码。

GetHashCode()

用作默认哈希函数。

(继承自 Object)
GetNamedDataSlot(String)

查找命名数据槽。 为了获得更好的性能,请改用带有属性标记的 ThreadStaticAttribute 字段。

GetType()

获取当前实例的 Type

(继承自 Object)
Interrupt()

中断处于线程状态的 WaitSleepJoin 线程。

Join()

阻止调用线程,直到此实例表示的线程终止,同时继续执行标准 COM 和 SendMessage 泵送。

Join(Int32)

阻止调用线程,直到此实例表示的线程终止或指定的时间过长,同时继续执行标准 COM 和 SendMessage 抽水。

Join(TimeSpan)

阻止调用线程,直到此实例表示的线程终止或指定的时间过长,同时继续执行标准 COM 和 SendMessage 抽水。

MemberwiseClone()

创建当前 Object的浅表副本。

(继承自 Object)
MemoryBarrier()

按如下方式同步内存访问:执行当前线程的处理器无法以在调用 MemoryBarrier() 之后的内存访问之后执行内存访问 MemoryBarrier()之前重新排序指令。

ResetAbort()
已过时.

Abort(Object)取消当前线程的请求。

Resume()
已过时.
已过时.
已过时.

恢复已挂起的线程。

SetApartmentState(ApartmentState)

在线程启动之前设置线程的公寓状态。

SetCompressedStack(CompressedStack)
已过时.
已过时.

将捕获 CompressedStack 应用到当前线程。

SetData(LocalDataStoreSlot, Object)

为该线程的当前域设置当前正在运行的线程上指定槽中的数据。 为了获得更好的性能,请改用带有属性标记的 ThreadStaticAttribute 字段。

Sleep(Int32)

挂起当前线程的指定毫秒数。

Sleep(TimeSpan)

暂停当前线程的指定时间量。

SpinWait(Int32)

使线程等待参数定义的 iterations 次数。

Start()

使操作系统将当前实例 Running的状态更改为 。

Start(Object)

使操作系统将当前实例 Running的状态更改为,并选择性地提供一个对象,其中包含线程执行的方法要使用的数据。

Suspend()
已过时.
已过时.
已过时.

挂起线程,或者如果线程已挂起,则不起作用。

ToString()

返回一个表示当前对象的字符串。

(继承自 Object)
TrySetApartmentState(ApartmentState)

在线程启动之前设置线程的公寓状态。

UnsafeStart()

使操作系统将当前实例 Running的状态更改为 。

UnsafeStart(Object)

使操作系统将当前实例 Running的状态更改为,并选择性地提供一个对象,其中包含线程执行的方法要使用的数据。

VolatileRead(Byte)
已过时.

读取字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。

VolatileRead(Double)
已过时.

读取字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。

VolatileRead(Int16)
已过时.

读取字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。

VolatileRead(Int32)
已过时.

读取字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。

VolatileRead(Int64)
已过时.

读取字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。

VolatileRead(IntPtr)
已过时.

读取字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。

VolatileRead(Object)
已过时.

读取字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。

VolatileRead(SByte)
已过时.

读取字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。

VolatileRead(Single)
已过时.

读取字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。

VolatileRead(UInt16)
已过时.

读取字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。

VolatileRead(UInt32)
已过时.

读取字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。

VolatileRead(UInt64)
已过时.

读取字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。

VolatileRead(UIntPtr)
已过时.

读取字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。

VolatileWrite(Byte, Byte)
已过时.

将值写入字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。

VolatileWrite(Double, Double)
已过时.

将值写入字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。

VolatileWrite(Int16, Int16)
已过时.

将值写入字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。

VolatileWrite(Int32, Int32)
已过时.

将值写入字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。

VolatileWrite(Int64, Int64)
已过时.

将值写入字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。

VolatileWrite(IntPtr, IntPtr)
已过时.

将值写入字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。

VolatileWrite(Object, Object)
已过时.

将值写入字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。

VolatileWrite(SByte, SByte)
已过时.

将值写入字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。

VolatileWrite(Single, Single)
已过时.

将值写入字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。

VolatileWrite(UInt16, UInt16)
已过时.

将值写入字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。

VolatileWrite(UInt32, UInt32)
已过时.

将值写入字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。

VolatileWrite(UInt64, UInt64)
已过时.

将值写入字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。

VolatileWrite(UIntPtr, UIntPtr)
已过时.

将值写入字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。

Yield()

导致调用线程让出执行权,以便另一个已准备好在当前处理器上运行的线程可以运行。 操作系统选择要屈服于的线程。

显式接口实现

名称 说明
_Thread.GetIDsOfNames(Guid, IntPtr, UInt32, UInt32, IntPtr)

将一组名称映射为对应的一组调度标识符。

_Thread.GetTypeInfo(UInt32, UInt32, IntPtr)

检索对象的类型信息,然后可以使用该信息获取接口的类型信息。

_Thread.GetTypeInfoCount(UInt32)

检索对象提供的类型信息接口的数量(0 或 1)。

_Thread.Invoke(UInt32, Guid, UInt32, Int16, IntPtr, IntPtr, IntPtr, IntPtr)

提供对对象公开的属性和方法的访问。

适用于

线程安全性

此类型是线程安全的。

另请参阅