Многопоточные приложения (C# и Visual Basic)

С помощью языков Visual Basic и C# можно создавать приложения, которые выполняют несколько задач одновременно. Задачи, которые потенциально могут задержать выполнение других задач, выполняются в отдельных потоках; такой способ организации работы приложения называется многопоточностью или свободным созданием потоков.

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

Примечание

Visual Studio 2010 и .NET Framework 4 улучшают поддержку параллельного программирования путем предоставления новой среды выполнения, новых типов библиотек классов и новых средств диагностики.Дополнительные сведения см. в разделе Параллельное программирование в .NET Framework.

Использование компонента BackgroundWorker

Наиболее надежный способ создания многопоточного приложения является использование компонента BackgroundWorker. Этот класс управляет отдельными потоками указанного метода обработки. Пример см. в разделе Пошаговое руководство. Многопоточность с помощью компонента BackgroundWorker (C# и Visual Basic).

Чтобы запустить операцию в фоновом режиме, необходимо создатьBackgroundWorker и отслеживать события, сообщающие о ходе выполнения операции и сигнализирующие о ее завершении. Можно создать объект BackgroundWorker программными средствами или перетащить его в форму из вкладки Компоненты Панели элементов. При создании BackgroundWorker в Forms Designer, оно появляется в Области компонента, и его свойства отображаются в окне Свойства.

Настройка выполнения операции в фоновом режиме

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

Чтобы начать операцию, вызовите RunWorkerAsync. Чтобы получать уведомления о ходе выполнения, необходимо обработать событие ProgressChanged. Если необходимо получать уведомление после завершения операции, обработайте событие RunWorkerCompleted.

Методы, обрабатывающие события ProgressChanged и RunWorkerCompleted имеют доступ к пользовательскому интерфейсу приложения, так как эти события вызываются в потоке, который вызвал метод RunWorkerAsync. Однако обработчик событий DoWork не может работать с объектами пользовательского интерфейса, поскольку он запускается в фоновом потоке.

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

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

Новый поток создается путем объявления переменной типа Thread и вызова конструктора, которому предоставляется имя процедуры или метода, которые требуется выполнить в новом потоке. См. пример в следующем коде.

Dim newThread As New System.Threading.Thread(AddressOf AMethod)
System.Threading.Thread newThread =
    new System.Threading.Thread(AMethod);

Запуск и остановка потоков

Чтобы начать выполнение нового потока, следует использовать метод Start, как показано в следующем примере кода.

newThread.Start()
newThread.Start();

Чтобы остановить выполнение потока, следует использовать метод Abort, как показано в следующем примере кода.

newThread.Abort()
newThread.Abort();

Помимо запуска и остановки потоки можно приостанавливать, вызывая метод Sleep или Suspend, возобновлять приостановленный поток методом Resume и уничтожать поток методом Abort.

Методы управления потоками

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

Метод

Действие

Start

Запускает поток.

Sleep

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

Suspend

Приостанавливает поток, когда он достигает безопасной точки.

Abort

Останавливает поток, когда он достигает безопасной точки.

Resume

Возобновляет работу приостановленного потока

Join

Приостанавливает текущий поток до тех пор, пока не будет завершен другой поток. При заданном времени ожидания этот метод возвращает значение True при условии, что другой поток закончится за это время.

Безопасные точки

Названия этих методов говорят сами за себя, однако концепция безопасных точек может оказаться новой для пользователя. Безопасные точки располагаются в тех местах кода, в которых среда CLR может безопасно выполнить автоматическую сборку мусора — процесс уничтожения неиспользуемых переменных и освобождения памяти. При вызове методов потока Abort или Suspend среда CLR анализирует код и определяет подходящее место для остановки потока.

Свойства потока

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

Свойство.

Значение

IsAlive

Содержит значение True, если поток активен.

IsBackground

Возвращает или задает логическое значение, которое указывает, является ли поток (должен ли являться) фоновым потоком. Фоновые потоки отличаются от основного потока лишь тем, что они не влияют на завершение процесса. Когда обработка всех основных потоков закончена, общеязыковая среда выполнения завершает процесс, применяя метод Abort к тем фоновым потокам, которые еще продолжают существовать.

Name

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

Priority

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

ApartmentState

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

ThreadState

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

Приоритеты потоков

Каждый поток имеет приоритетное свойство, которое определяет, какую часть процессорного времени он должен занять при выполнении. Операционная система выделяет более длинные отрезки времени на потоки с высоким приоритетом и более короткие на потоки с низким приоритетом. Новые потоки создаются со значением Normal, но можно изменить свойство Priority на любое значение в перечислении ThreadPriority.

Описание различных приоритетов потоков см. в разделе ThreadPriority.

Основные и фоновые потоки

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

Использование многопоточности для форм и элементов управления

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

  • По возможности методы элемента управления должны выполняться в том же потоке, в котором был создан этот элемент. Если необходимо вызвать метод элемента управления из другого потока, необходимо использовать для вызова метода метод Invoke.

  • Не используйте оператор SyncLock (Visual Basic) или lock (C#) для блокировки потоков, работающих с элементами управления или формами. Поскольку методы элементов управления и форм иногда выполняют обратный вызов вызывающей процедуры, можно непреднамеренно вызвать взаимоблокировку — ситуацию, когда два потока ожидают друг от друга выполнения действий, необходимых для дальнейшей работы приложения.

См. также

Ссылки

Синхронизация потоков (C# и Visual Basic)

Invoke

InvokeRequired

Thread

Основные понятия

Параметры и возвращаемые значения для многопоточных процедур (C# и Visual Basic)

Другие ресурсы

Многопоточность в компонентах

Создание потока с помощью Visual C#