Поток – последовательность инструкций, которую выполняет компьютер. Приложение может иметь несколько таких последовательностей, все что необходимо – каждый раз при создаии потока указывать метод, в котором должно начаться выполнение.
Первый поток (главный) приложения всегда запускает 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.
Проблемы синхронизации потоков:
- злоупотребление синхронизацией (как следстие понижение производительности из-за простоев);
- взаимоблокировки блокировки (два потока ничего не делают, ожидая, когда каждый из них снимет свою блокировку);
- состязания (несколько потоков пытаются получить доступ к одним и тем же данным).