Класс System.Threading.Thread

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

Класс Thread создает и управляет потоком, задает приоритет и получает его состояние.

При запуске процесса среда CLR автоматически создает один поток переднего плана для выполнения кода приложения. Наряду с этим основным потоком переднего плана процесс может создать один или несколько потоков для выполнения части кода программы, связанной с процессом. Эти потоки могут выполняться либо на переднем плане, либо в фоновом режиме. Кроме того, можно использовать ThreadPool класс для выполнения кода в рабочих потоках, управляемых средой CLR.

Запуск потока

Поток запускается путем предоставления делегата, представляющего метод, который поток выполняется в конструкторе классов. Затем вызывается Start метод для начала выполнения.

Конструкторы Thread могут принимать один из двух типов делегатов в зависимости от того, можно ли передать аргумент в метод для выполнения:

  • Если метод не имеет аргументов, передайте ThreadStart делегат конструктору. Он имеет подпись:

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

    В следующем примере создается и запускается поток, который выполняет ExecuteInForeground метод. Метод отображает сведения о некоторых свойствах потока, а затем выполняет цикл, в котором он приостанавливается в течение половины секунды и отображает истекшее количество секунд. Когда поток выполняется по крайней мере пять секунд, цикл заканчивается и поток завершает выполнение.

    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 свойством, а также язык и региональные параметры пользовательского интерфейса, представленные свойством CurrentUICulture . Текущий язык и региональные параметры поддерживает такие операции, как анализ и форматирование, сравнение строк и сортировка, а также управляет системой записи и календарем, используемым потоком. Текущий язык и региональные параметры пользовательского интерфейса обеспечивают получение ресурсов в файлах ресурсов с учетом языка и региональных параметров.

Важно!

CurrentUICulture Свойства CurrentCulture и свойства не работают надежно при использовании с любым потоком, кроме текущего потока. В платформа .NET Framework чтение этих свойств является надежным, хотя установка этих свойств для потока, отличного от текущего потока, не является. В .NET Core возникает исключение, InvalidOperationException если поток пытается считывать или записывать эти свойства в другом потоке. Мы рекомендуем использовать CultureInfo.CurrentCulture свойства и CultureInfo.CurrentUICulture свойства для получения и задания текущего языка и региональных параметров.

При создании экземпляра нового потока язык и региональные параметры и региональные параметры пользовательского интерфейса определяются текущим языком и языком и региональными параметрами системы и пользовательского интерфейса, а не языком и языком и региональными параметрами пользовательского интерфейса потока, из которого создается новый поток. Это означает, например, что если текущий язык и региональные параметры системы — английский (США) и текущий язык и региональные параметры основного потока приложения — французский (Франция), язык и региональные параметры нового потока, созданного путем вызова Thread(ParameterizedThreadStart) конструктора из основного потока, — английский (США), а не французский (Франция). Дополнительные сведения см. в разделе CultureInfo "Язык и потоки" раздела класса.

Важно!

Это не верно для потоков, выполняющих асинхронные операции для приложений, предназначенных для платформа .NET Framework версии 4.6 и более поздних версий. В этом случае язык и региональные параметры и региональные параметры пользовательского интерфейса являются частью контекста асинхронной операции; Поток, на котором выполняется асинхронная операция по умолчанию, наследует язык и региональные параметры и региональные параметры пользовательского интерфейса потока, из которого была запущена асинхронная операция. Дополнительные сведения см. в разделе CultureInfo "Региональные параметры и асинхронные операции на основе задач" примечания класса.

Чтобы убедиться, что все потоки, выполняемые в приложении, имеют одинаковый язык и региональные параметры и региональные параметры пользовательского интерфейса.

  • Можно передать объект, представляющий этот язык и региональные CultureInfo параметры делегату ParameterizedThreadStart или методу ThreadPool.QueueUserWorkItem(WaitCallback, Object) .

  • Для приложений, работающих на платформа .NET Framework версии 4.5 и более поздних версий, можно определить язык и региональные параметры и региональные параметры пользовательского интерфейса, назначенные всем потокам, созданным в домене приложения, задав значение CultureInfo.DefaultThreadCurrentCulture и CultureInfo.DefaultThreadCurrentUICulture свойства. Обратите внимание, что это параметр домена для каждого приложения.

Дополнительные сведения и примеры см. в разделе CultureInfo "Язык и потоки" примечаний класса.

Получение сведений о потоках управления ими

Вы можете получить ряд значений свойств, которые предоставляют сведения о потоке. В некоторых случаях эти значения свойств также можно задать для управления операцией потока. К этим свойствам потока относятся следующие:

  • Имя. Name — это свойство для записи, которое можно использовать для идентификации потока. Значение по умолчанию — null.

  • Хэш-код, который можно получить путем вызова GetHashCode метода. Хэш-код можно использовать для уникальной идентификации потока; в течение всего времени существования потока его хэш-код не будет сталкиваться со значением из любого другого потока независимо от домена приложения, из которого вы получаете значение.

  • Идентификатор потока. Значение свойства только ManagedThreadId для чтения назначается средой выполнения и однозначно идентифицирует поток в рамках своего процесса.

    Примечание.

    ThreadId операционной системы не имеет фиксированного отношения с управляемым потоком, так как неуправляемый узел может управлять отношением между управляемым и неуправляемым потоками. В частности, сложный узел может использовать API размещения СРЕДЫ CLR для планирования множества управляемых потоков для одного потока операционной системы или перемещения управляемого потока между различными потоками операционной системы.

  • Текущее состояние потока. В течение существования поток всегда находится в одном или нескольких состояниях, определенных свойством 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.