C# → Потоки System.Threading

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

Первый поток (главный) приложения всегда запускает Main(). На компьютерах с одним процессором в действительности операционная система Windows создает впечатление одновременности действий с помощью вытесняющей многозадачности.

Thread DepthChangeThread = new Thread(); // создаем поток

DepthChangeThread.Name = «Поток изменяющий глубину цвета изображения»;

Для запуска потока необходимо указать какой метод в нем будет выполняться. Этот метод не должен принимать параметров и должен возвращать void. Поток запускают вызовом метода Thread.Start(), передавая ему сведения о точке входа с помощью делегата. Такой делегат уже объявлен в пространстве имен System.Threadnig, поэтому его объявлять не нужно (public delegate void ThreadStart()), достаточно просто создать его экземпляр.

    class Work
    {
        public static void DoWork()
        {
            for (int i = 0; i < 100000; i++) { Console.Write("HELLO");}
        }
    } ...
        static void CreateThread()
        {
            ThreadStart ThreadEntryPoint = new ThreadStart(Work.DoWork);
            Thread DepthChangeThread = new Thread(ThreadEntryPoint); // создаем поток
            DepthChangeThread.Name = "Поток изменяющий глубину цвета изображения";
            DepthChangeThread.Start();
        }

DepthChangeThread.Suspend() – приостанавливает процесс выполнения потока.

DepthChangeThread.Resume() – возобновляет процесс выполнения потока.

DepthChangeThread.Abort() – прекращает выполнение потока.

Методы Suspend() и Abort() необязательно сработают сразу после вызова. В случае Suspend() среда .NET может остановить поток через несколько инструкций. В результате может потребоваться дождаться того момента, когда поток будет остановлен при помощи метода Join().

Thread myOwnThread = Thread.CurrentThread; // позволяет получить ссылку на главный поток
Thread.Sleep(200); // приостанавливает текущий поток на заданный период времени

Приоритеты потоков определены как значения ThreadPriorityEnumeration, возможные значения: Highest, AboveNormal, Normal, BelowNormal, Lowest. Каждый процесс имеет базовый приоритет, а перечисленные значения задаются относительно приоритета процесса.

DepthChangeThread.Priority = ThreadPriority.AboveNormal;

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

С# обеспечивает простой способ синхронизации доступа к переменным с помощью ключевого слова lock. Операторы lock используют объект, известный как взаимная исключающая блокировка (или мьютекс), для переменной записанной в круглых скобках.

lock(x) { DoSomthing(); }

Пока переменная блокирована, другой поток не может получить к ней доступ. Если во время исполнения приведенного кода процесс теряет квант времени, а другой процесс получает его и пытается осуществить доступ к переменной, ему будет отказано в доступе. Windows приостановит другой поток до того момента, когда переменная будет освобождена. Остальные механизмы управления доступом к переменным используются с помощью базового класса System.Threading.Monitor.

Проблемы синхронизации потоков:

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