автордың кітабынан сөз тіркестері C# Concurrency. Асинхронное программирование и многопоточность
Многопоточность — это настолько быстрое переключение между несколькими потоками, которые выполняются на одном и том же процессоре, что создается ощущение, будто все они выполняются одновременно.
• Поток — это последовательность команд, которые могут обрабатываться в один и
Когда использовать Task.Run
Используйте Task.Run для:
• кода, использующего async/await;
• коротких задач.
Не используйте Task.Run для:
• синхронных задач, выполняющихся продолжительное время.
Используйте ThreadPool.QueueUserWorkItem для:
• коротких задач.
Не используйте ThreadPool.QueueUserWorkItem:
• для долго выполняющихся задач;
• когда нужно изменить свойства потока;
• с асинхронными операциями на основе Task;
• с инструкциями async/await.
Используйте Thread.Start:
• для долго выполняющегося кода;
• если нужно изменить свойства потока, такие как информация о языке и локали, признак выполнения в фоне, COM-апартаменты и т.д. (обо всех настройках потока мы поговорим ближе к концу этой главы).
Не используйте Thread.Start для:
• асинхронного кода;
• коротких задач.
Итак, при использовании задач без async/await можно обращаться к свойствам IsCompleted или Status, чтобы спросить: «Мы уже приехали?» И, так же как при поездке в машине, не стоит спрашивать слишком часто. Другой вариант — использовать ContinueWith, чтобы задача сообщила вам, когда она завершится («Разбуди меня, когда приедем»). Наконец, можно вызвать Wait или обратиться к Result, чтобы сделать задачу синхронной, но это неэффективно и опасно, потому что такой вызов блокирует поток до завершения задачи (вызов Wait или обращение к Result после завершения задачи совершенно безопасны и эффективны, потому что результат уже доступен и в блокировке нет необходимости).
CancellationToken — это просто флаг. Сам по себе он ничего не отменяет.
• Для вызова метода обратного вызова при отмене можно использовать CancellationToken.Register.
• Для реализации тайм-аутов можно использовать CancellationTokenSource.CancelAfter.
• CancellationTokenSource.CreateLinkedTokenSource позволяет создать CancellationTokenSource из одного или нескольких существующих объектов CancellationToken и управлять им.
• Если нужно передать CancellationToken, который никогда не отменится, используйте CancellationToken.None.
Например, когда пишется синхронный код, использующий API, в котором есть только один асинхронный метод на основе Task, то лучшим решением будет вызов метода Task.Wait или чтение свойства Task<T>.Result
Сделать асинхронный код похожим на обычный — это сама по себе большая проблема, потому что раньше каждую последовательность операций приходилось разбивать на небольшие части (по границам асинхронных операций) и вызывать необходимую часть в нужное время. Неудивительно, что это приводит к путанице при написании кода.
• Использование Task и Task<T> в синхронном коде.
Этот пример может показаться слишком наивным, потому что он явно неэффективен, и наш повар будет тратить слишком много времени, чтобы записать на бумажке, на чем он остановился, или прочитать с бумажки, чтобы понять, с какого места продолжить работу. Однако именно так работает многопоточность. Внутри процессора есть таймер, который сигнализирует, когда он должен переключиться на следующий поток, и при каждом переключении процессор сохраняет информацию о том, что он делал, и загружает состояние другого потока (это называется переключением контекста).
