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
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
public sealed class Thread : System.Runtime.ConstrainedExecution.CriticalFinalizerObject
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
[<System.Runtime.InteropServices.ComVisible(true)>]
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
type Thread = class
    inherit CriticalFinalizerObject
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
属性
实现

示例

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

// [C++]
// Compile using /clr option.
using namespace System;
using namespace System::Threading;

// Simple threading scenario:  Start a Shared method running
// on a second thread.
public ref class ThreadExample
{
public:

   // 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.
   static void ThreadProc()
   {
      for ( int i = 0; i < 10; i++ )
      {
         Console::Write(  "ThreadProc: " );
         Console::WriteLine( i );
         
         // Yield the rest of the time slice.
         Thread::Sleep( 0 );

      }
   }

};

int main()
{
   Console::WriteLine( "Main thread: Start a second thread." );
   
   // Create the thread, passing a ThreadStart delegate that
   // represents the ThreadExample::ThreadProc method.  For a 
   // delegate representing a static method, no object is
   // required.
   Thread^ oThread = gcnew Thread( gcnew ThreadStart( &ThreadExample::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 oThread->Start() to see the difference.
   oThread->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." );
   oThread->Join();
   Console::WriteLine(  "Main thread: ThreadProc.Join has returned.  Press Enter to end program." );
   Console::ReadLine();
   return 0;
}
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();
    }
}
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.  

注解

进程启动时,公共语言运行时会自动创建单个前台线程来执行应用程序代码。 除了此主前台线程,进程还可以创建一个或多个线程来执行与进程关联的部分程序代码。 这些线程可以在前台或后台执行。 此外,可以使用 类在由公共语言运行时管理的工作线程上 ThreadPool 执行代码。

在本节中

启动线程
检索 Thread 对象
前台线程和后台线程
区域性和线程
获取有关和控制线程的信息

启动线程

通过提供一个委托来启动线程,该委托表示线程在其类构造函数中执行的方法。 然后调用 Start 方法以开始执行。

构造函数可以使用两种委托类型之一,具体取决于是否可以将参数 Thread 传递给要执行的方法:

  • 如果方法没有参数,则向 ThreadStart 构造函数传递委托。 它具有签名:

    public delegate void ThreadStart()  
    
    Public Delegate Sub ThreadStart()  
    

    以下示例创建并启动执行 方法的 ExecuteInForeground 线程。 方法显示有关某些线程属性的信息,然后执行一个循环,该循环暂停半秒并显示已用秒数。 当线程已执行至少五秒时,循环结束,线程终止执行。

    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
    
    Imports System.Diagnostics
    Imports System.Threading
    
    Module Example
       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
    
    Imports System.Diagnostics
    Imports System.Threading
    
    Module Example
       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 对象

可以使用 (属性中的Visual Basic) 从线程正在执行的代码检索对当前正在执行的 Shared 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
Imports System.Threading

Module Example
   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...
Imports System.Diagnostics
Imports System.Threading

Module Example
   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...

区域性和线程

每个线程都有一个区域性(由 属性表示)和一个 UI 区域性( CurrentCulture 由 属性 CurrentUICulture 表示)。 当前区域性支持诸如分析和格式设置、字符串比较和排序等区分区域性的操作,还控制线程使用的写入系统和日历。 当前的 UI 区域性提供对资源文件中资源进行区分区域性的检索。

重要

与除当前线程外的任何线程一起使用时, 和 CurrentCulture CurrentUICulture 属性无法可靠地工作。 在这种情况下.NET Framework读取这些属性是可靠的,尽管为当前线程外的其他线程设置这些属性并不可靠。 在 .NET Core 上,如果线程尝试在不同的线程上读取 InvalidOperationException 或写入这些属性,则会引发 。 建议使用 和 属性 CultureInfo.CurrentCulture CultureInfo.CurrentUICulture 来检索和设置当前区域性。

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

重要

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

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

有关详细信息和示例,请参阅 类主题的"区域性和线程 CultureInfo "部分。

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

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

  • 名称。 Name 是可用于标识线程的一次写入属性。 它的默认值为 null

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

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

    备注

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

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

  • 计划优先级级别,由 属性 ThreadPriority 定义。 尽管可以设置此值来请求线程的优先级,但不能保证操作系统遵守此值。

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

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

构造函数

Thread(ParameterizedThreadStart)

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

Thread(ParameterizedThreadStart, Int32)

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

Thread(ThreadStart)

初始化 Thread 类的新实例。

Thread(ThreadStart, Int32)

初始化 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)

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

适用于

线程安全性

此类型是线程安全的。

另请参阅