C # - Многопоточность

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

Потоки lightweight processes. Одним из распространенных примеров использования потоков является реализация параллельного программирования в современных операционных системах. Использование потоков сокращает потери цикла ЦП и повышает эффективность приложения.

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

Жизненный цикл резьбы

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

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

  • The Unstarted State - Это ситуация, когда экземпляр потока создается, но метод Start не вызывается.

  • The Ready State - Это ситуация, когда поток готов к запуску и ожидает цикла процессора.

  • The Not Runnable State - Поток не исполняется, когда

    • Метод сна был вызван
    • Вызван метод ожидания
    • Заблокировано операциями ввода-вывода
  • The Dead State - Это ситуация, когда поток завершает выполнение или прерывается.

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

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

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

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

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

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

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

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

CurrentContext

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

2

CurrentCulture

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

3

CurrentPrinciple

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

4

CurrentThread

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

5

CurrentUICulture

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

6

ExecutionContext

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

7

IsAlive

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

8

IsBackground

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

9

IsThreadPoolThread

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

10

ManagedThreadId

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

11

Name

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

12

Priority

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

13

ThreadState

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

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

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

public void Abort()

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

2

public static LocalDataStoreSlot AllocateDataSlot()

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

3

public static LocalDataStoreSlot AllocateNamedDataSlot(string name)

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

4

public static void BeginCriticalRegion()

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

5

public static void BeginThreadAffinity()

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

6

public static void EndCriticalRegion()

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

7

public static void EndThreadAffinity()

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

8

public static void FreeNamedDataSlot(string name)

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

9

public static Object GetData(LocalDataStoreSlot slot)

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

10

public static AppDomain GetDomain()

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

11

public static AppDomain GetDomainID()

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

12

public static LocalDataStoreSlot GetNamedDataSlot(string name)

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

13

public void Interrupt()

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

14

public void Join()

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

15

public static void MemoryBarrier()

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

16

public static void ResetAbort()

Отменяет запрос Abort для текущего потока.

17

public static void SetData(LocalDataStoreSlot slot, Object data)

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

18

public void Start()

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

19

public static void Sleep(int millisecondsTimeout)

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

20

public static void SpinWait(int iterations)

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

21 год

public static byte VolatileRead(ref byte address)

public static double VolatileRead(ref double address)

public static int VolatileRead(ref int address)

public static Object VolatileRead(ref Object address)

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

22

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

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

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

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

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

23

public static bool Yield()

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

Создание потоков

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

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

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() метод для приостановки потока на определенный период времени.

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 , если таковой имеется.

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

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();
      }
   }
}

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

In Main: Creating the Child thread
Child thread starts
0
1
2
In Main: Aborting the Child thread
Thread Abort Exception
Couldn't catch the Thread Exception