Учебники

C # – многопоточность

Поток определяется как путь выполнения программы. Каждый поток определяет уникальный поток управления. Если ваше приложение включает в себя сложные и трудоемкие операции, то часто бывает полезно установить разные пути выполнения или потоки, при этом каждый поток выполняет определенную работу.

Нити – это легкие процессы . Одним из распространенных примеров использования потоков является реализация параллельного программирования в современных операционных системах. Использование потоков экономит время процессора и увеличивает эффективность приложения.

До сих пор мы писали программы, в которых один поток выполняется как один процесс, который является запущенным экземпляром приложения. Тем не менее, таким образом, приложение может выполнять одну работу за раз. Чтобы заставить его выполнять более одной задачи одновременно, его можно разделить на более мелкие потоки.

Жизненный цикл темы

Жизненный цикл потока начинается, когда создается объект класса System.Threading.Thread, и заканчивается, когда поток завершается или завершает выполнение.

Ниже приведены различные состояния в жизненном цикле потока –

  • Состояние без старта – это ситуация, когда создается экземпляр потока, но метод Start не вызывается.

  • Состояние готовности – это ситуация, когда поток готов к работе и ожидает цикл ЦП.

  • Not Runnable State – поток не является исполняемым, когда

    • Метод сна был вызван
    • Метод ожидания был вызван
    • Заблокировано операциями ввода / вывода
  • Мертвое состояние – это ситуация, когда поток завершает выполнение или прерывается.

Состояние без старта – это ситуация, когда создается экземпляр потока, но метод Start не вызывается.

Состояние готовности – это ситуация, когда поток готов к работе и ожидает цикл ЦП.

Not Runnable State – поток не является исполняемым, когда

Мертвое состояние – это ситуация, когда поток завершает выполнение или прерывается.

Основная тема

В C # класс System.Threading.Thread используется для работы с потоками. Это позволяет создавать и получать доступ к отдельным потокам в многопоточном приложении. Первый поток, выполняемый в процессе, называется основным потоком.

Когда программа на C # начинает выполнение, основной поток создается автоматически. Потоки, созданные с использованием класса Thread , называются дочерними потоками основного потока. Вы можете получить доступ к потоку, используя свойство CurrentThread класса Thread.

Следующая программа демонстрирует выполнение основного потока –

Live Demo

using System;
using System.Threading;

namespace MultithreadingApplication {
   class MainThreadProgram {
      static void Main(string[] args) {
         Thread th = Thread.CurrentThread;
         th.Name = "MainThread";
         
         Console.WriteLine("This is {0}", th.Name);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат –

This is MainThread

Свойства и методы класса Thread

В следующей таблице приведены некоторые наиболее часто используемые свойства класса Thread.

Sr.No. Описание недвижимости
1

CurrentContext

Получает текущий контекст, в котором выполняется поток.

2

CurrentCulture

Получает или задает культуру для текущего потока.

3

CurrentPrinciple

Получает или задает текущего участника потока (для безопасности на основе ролей).

4

CurrentThread

Получает текущий запущенный поток.

5

CurrentUICulture

Получает или задает текущую культуру, используемую Resource Manager для поиска ресурсов, специфичных для данной культуры, во время выполнения.

6

ExecutionContext

Получает объект ExecutionContext, который содержит информацию о различных контекстах текущего потока.

7

Является живым

Получает значение, указывающее состояние выполнения текущего потока.

8

IsBackground

Получает или задает значение, указывающее, является ли поток фоновым потоком.

9

IsThreadPoolThread

Получает значение, указывающее, принадлежит ли поток к пулу управляемых потоков.

10

ManagedThreadId

Получает уникальный идентификатор для текущего управляемого потока.

11

название

Получает или задает имя потока.

12

приоритет

Получает или задает значение, указывающее приоритет планирования потока.

13

ThreadState

Получает значение, содержащее состояния текущего потока.

CurrentContext

Получает текущий контекст, в котором выполняется поток.

CurrentCulture

Получает или задает культуру для текущего потока.

CurrentPrinciple

Получает или задает текущего участника потока (для безопасности на основе ролей).

CurrentThread

Получает текущий запущенный поток.

CurrentUICulture

Получает или задает текущую культуру, используемую Resource Manager для поиска ресурсов, специфичных для данной культуры, во время выполнения.

ExecutionContext

Получает объект ExecutionContext, который содержит информацию о различных контекстах текущего потока.

Является живым

Получает значение, указывающее состояние выполнения текущего потока.

IsBackground

Получает или задает значение, указывающее, является ли поток фоновым потоком.

IsThreadPoolThread

Получает значение, указывающее, принадлежит ли поток к пулу управляемых потоков.

ManagedThreadId

Получает уникальный идентификатор для текущего управляемого потока.

название

Получает или задает имя потока.

приоритет

Получает или задает значение, указывающее приоритет планирования потока.

ThreadState

Получает значение, содержащее состояния текущего потока.

В следующей таблице приведены некоторые из наиболее часто используемых методов класса Thread.

Sr.No. Метод и описание
1

публичный void Abort ()

Вызывает исключение ThreadAbortException в потоке, в котором он вызывается, чтобы начать процесс завершения потока. Вызов этого метода обычно завершает поток.

2

public static LocalDataStoreSlot AllocateDataSlot ()

Выделяет безымянный слот данных во всех потоках. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

3

public static LocalDataStoreSlot AllocateNamedDataSlot (имя строки)

Выделяет именованный слот данных во всех потоках. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

4

public static void BeginCriticalRegion ()

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

5

public static void BeginThreadAffinity ()

Уведомляет хост, что управляемый код собирается выполнить инструкции, которые зависят от идентификатора текущего физического потока операционной системы.

6

public static void EndCriticalRegion ()

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

7

public static void EndThreadAffinity ()

Уведомляет хост, что управляемый код завершил выполнение инструкций, которые зависят от идентификатора текущего физического потока операционной системы.

8

публичная статическая пустота FreeNamedDataSlot (имя строки)

Устраняет связь между именем и слотом для всех потоков в процессе. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

9

открытый статический объект GetData (слот LocalDataStoreSlot)

Извлекает значение из указанного слота в текущем потоке в текущем домене текущего потока. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

10

публичный статический AppDomain GetDomain ()

Возвращает текущий домен, в котором работает текущий поток.

11

публичный статический AppDomain GetDomainID ()

Возвращает уникальный идентификатор домена приложения

12

public static LocalDataStoreSlot GetNamedDataSlot (имя строки)

Ищет именованный слот данных. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

13

public void Interrupt ()

Прерывает поток, находящийся в состоянии потока WaitSleepJoin.

14

public void Join ()

Блокирует вызывающий поток до тех пор, пока поток не завершится, продолжая при этом выполнять стандартную прокачку COM и SendMessage. Этот метод имеет разные перегруженные формы.

15

public static void MemoryBarrier ()

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

16

общедоступная статическая пустота ResetAbort ()

Отменяет прерывание, запрошенное для текущего потока.

17

public static void SetData (слот LocalDataStoreSlot, данные объекта)

Устанавливает данные в указанном слоте текущего запущенного потока для текущего домена этого потока. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

18

public void Start ()

Начинает поток.

19

public static void Sleep (int millisecondsTimeout)

Заставляет нить приостановиться на некоторое время.

20

общедоступная статическая пустота SpinWait (int iterations)

Заставляет поток ждать количество раз, определенное параметром iterations

21

открытый статический байт VolatileRead (адрес байта)

public static double VolatileRead (ссылка на двойной адрес)

public static int VolatileRead (ref int address)

публичный статический объект VolatileRead (ссылка на адрес объекта)

Читает значение поля. Значение является последним, записанным любым процессором в компьютере, независимо от количества процессоров или состояния кэша процессора. Этот метод имеет разные перегруженные формы. Только некоторые из них приведены выше.

22

public static void VolatileWrite (адрес байта, значение байта)

public static void VolatileWrite (ссылка двойной адрес, двойное значение)

public static void VolatileWrite (ref int address, int value)

public static void VolatileWrite (ref Адрес объекта, Значение объекта)

Немедленно записывает значение в поле, чтобы оно было доступно всем процессорам компьютера. Этот метод имеет разные перегруженные формы. Только некоторые из них приведены выше.

23

public static bool Yield ()

Заставляет вызывающий поток передать выполнение другому потоку, который готов к запуску на текущем процессоре. Операционная система выбирает поток для уступки.

публичный void Abort ()

Вызывает исключение ThreadAbortException в потоке, в котором он вызывается, чтобы начать процесс завершения потока. Вызов этого метода обычно завершает поток.

public static LocalDataStoreSlot AllocateDataSlot ()

Выделяет безымянный слот данных во всех потоках. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

public static LocalDataStoreSlot AllocateNamedDataSlot (имя строки)

Выделяет именованный слот данных во всех потоках. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

public static void BeginCriticalRegion ()

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

public static void BeginThreadAffinity ()

Уведомляет хост, что управляемый код собирается выполнить инструкции, которые зависят от идентификатора текущего физического потока операционной системы.

public static void EndCriticalRegion ()

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

public static void EndThreadAffinity ()

Уведомляет хост, что управляемый код завершил выполнение инструкций, которые зависят от идентификатора текущего физического потока операционной системы.

публичная статическая пустота FreeNamedDataSlot (имя строки)

Устраняет связь между именем и слотом для всех потоков в процессе. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

открытый статический объект GetData (слот LocalDataStoreSlot)

Извлекает значение из указанного слота в текущем потоке в текущем домене текущего потока. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

публичный статический AppDomain GetDomain ()

Возвращает текущий домен, в котором работает текущий поток.

публичный статический AppDomain GetDomainID ()

Возвращает уникальный идентификатор домена приложения

public static LocalDataStoreSlot GetNamedDataSlot (имя строки)

Ищет именованный слот данных. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

public void Interrupt ()

Прерывает поток, находящийся в состоянии потока WaitSleepJoin.

public void Join ()

Блокирует вызывающий поток до тех пор, пока поток не завершится, продолжая при этом выполнять стандартную прокачку COM и SendMessage. Этот метод имеет разные перегруженные формы.

public static void MemoryBarrier ()

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

общедоступная статическая пустота ResetAbort ()

Отменяет прерывание, запрошенное для текущего потока.

public static void SetData (слот LocalDataStoreSlot, данные объекта)

Устанавливает данные в указанном слоте текущего запущенного потока для текущего домена этого потока. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

public void Start ()

Начинает поток.

public static void Sleep (int millisecondsTimeout)

Заставляет нить приостановиться на некоторое время.

общедоступная статическая пустота SpinWait (int iterations)

Заставляет поток ждать количество раз, определенное параметром iterations

открытый статический байт VolatileRead (адрес байта)

public static double VolatileRead (ссылка на двойной адрес)

public static int VolatileRead (ref int address)

публичный статический объект VolatileRead (ссылка на адрес объекта)

Читает значение поля. Значение является последним, записанным любым процессором в компьютере, независимо от количества процессоров или состояния кэша процессора. Этот метод имеет разные перегруженные формы. Только некоторые из них приведены выше.

public static void VolatileWrite (адрес байта, значение байта)

public static void VolatileWrite (ссылка двойной адрес, двойное значение)

public static void VolatileWrite (ref int address, int value)

public static void VolatileWrite (ref Адрес объекта, Значение объекта)

Немедленно записывает значение в поле, чтобы оно было доступно всем процессорам компьютера. Этот метод имеет разные перегруженные формы. Только некоторые из них приведены выше.

public static bool Yield ()

Заставляет вызывающий поток передать выполнение другому потоку, который готов к запуску на текущем процессоре. Операционная система выбирает поток для уступки.

Создание тем

Потоки создаются путем расширения класса Thread. Затем расширенный класс Thread вызывает метод Start (), чтобы начать выполнение дочернего потока.

Следующая программа демонстрирует концепцию –

Live Demo

using System;
using System.Threading;

namespace MultithreadingApplication {
   class ThreadCreationProgram {
      public static void CallToChildThread() {
         Console.WriteLine("Child thread starts");
      }
      static void Main(string[] args) {
         ThreadStart childref = new ThreadStart(CallToChildThread);
         Console.WriteLine("In Main: Creating the Child thread");
         Thread childThread = new Thread(childref);
         childThread.Start();
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат –

In Main: Creating the Child thread
Child thread starts

Управление потоками

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

В следующем примере демонстрируется использование метода sleep () для приостановки потока на определенный период времени.

Live Demo

using System;
using System.Threading;

namespace MultithreadingApplication {
   class ThreadCreationProgram {
      public static void CallToChildThread() {
         Console.WriteLine("Child thread starts");
         
         // the thread is paused for 5000 milliseconds
         int sleepfor = 5000; 
         
         Console.WriteLine("Child Thread Paused for {0} seconds", sleepfor / 1000);
         Thread.Sleep(sleepfor);
         Console.WriteLine("Child thread resumes");
      }
      
      static void Main(string[] args) {
         ThreadStart childref = new ThreadStart(CallToChildThread);
         Console.WriteLine("In Main: Creating the Child thread");
         
         Thread childThread = new Thread(childref);
         childThread.Start();
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат –

In Main: Creating the Child thread
Child thread starts
Child Thread Paused for 5 seconds
Child thread resumes

Уничтожение Тем

Метод Abort () используется для уничтожения потоков.

Среда выполнения прерывает поток, создавая исключение ThreadAbortException . Это исключение не может быть перехвачено, элемент управления отправляется в блок finally , если таковой имеется.

Следующая программа иллюстрирует это –

Live Demo

using System;
using System.Threading;

namespace MultithreadingApplication {
   class ThreadCreationProgram {
      public static void CallToChildThread() {
         try {
            Console.WriteLine("Child thread starts");
            
            // do some work, like counting to 10
            for (int counter = 0; counter <= 10; counter++) {
               Thread.Sleep(500);
               Console.WriteLine(counter);
            }
            
            Console.WriteLine("Child Thread Completed");
         } catch (ThreadAbortException e) {
            Console.WriteLine("Thread Abort Exception");
         } finally {
            Console.WriteLine("Couldn't catch the Thread Exception");
         }
      }
      static void Main(string[] args) {
         ThreadStart childref = new ThreadStart(CallToChildThread);
         Console.WriteLine("In Main: Creating the Child thread");
         
         Thread childThread = new Thread(childref);
         childThread.Start();
         
         //stop the main thread for some time
         Thread.Sleep(2000);
         
         //now abort the child
         Console.WriteLine("In Main: Aborting the Child thread");
         
         childThread.Abort();
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат –