Cамоучитель по VB.NET

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



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

Public Class WillUseThreads

Public Sub SubtractFromCounter()

Dim count As Integer

Do While True count -= 1

Console.WriteLlne("Am in another thread and counter ="

& count)

Loop

End Sub

End Class

Поскольку условие цикла Do остается истинным всегда, можно подумать, что ничто не помешает выполнению процедуры SubtractFromCounter. Тем не менее в многопоточном приложении это не всегда так.

В следующем фрагменте приведена процедура Sub Main, запускающая поток, и команда Imports:



Option Strict On Imports System.Threading Module Modulel

Sub Main()

1 Dim myTest As New WillUseThreads()

2 Dim bThreadStart As New ThreadStart(AddressOf _

myTest.SubtractFromCounter)

3 Dim bThread As New Thread(bThreadStart)

4 ' bThread.Start()

Dim i As Integer

5 Do While True

Console.WriteLine("In main thread and count is " & i) i += 1

Loop

End Sub

End Module

Давайте последовательно разберем наиболее принципиальные моменты. Прежде всего процедура Sub Man n всегда работает в главном потоке (main thread). В програм-мах .NET всегда работают минимум два потока: главный и поток сборки мусора. В строке 1 создается новый экземпляр тестового класса. В строке 2 мы создаем делегат ThreadStart и передаем адрес процедуры SubtractFromCounter экземпляра тестового класса, созданного в строке 1 (эта процедура вызывается без параметров). Благодаря импортированию пространства имен Threading длинное имя можно не указывать. Объект нового потока создается в строке 3. Обратите внимание на передачу делегата ThreadStart при вызове конструктора класса Thread. Некоторые программисты предпочитают объединять эти две строки в одну логическую строку:

Dim bThread As New Thread(New ThreadStarttAddressOf _

myTest.SubtractFromCounter))

Наконец, строка 4 «запускает» поток, для чего вызывается метод Start экземпляра класса Thread, созданного для делегата ThreadStart. Вызывая этот метод, мы указываем операционной системе, что процедура Subtract должна работать в отдельном потоке.

Слово «запускает» в предыдущем абзаце заключено в кавычки, поскольку в этом случае наблюдается одна из многих странностей многопоточного программирования: вызов Start не приводит к фактическому запуску потока! Он всего лишь сообщает, что операционная система должна запланировать выполнение указанного потока, но непосредственный запуск находится вне контроля программы. Вам не удастся начать выполнение потоков по своему усмотрению, потому что выполнением потоков всегда распоряжается операционная система. В одном из дальнейших разделов вы узнаете, как при помощи приоритета заставить операционную систему побыстрее запустить ваш поток.

На Рисунок 10.1 показан пример того, что может произойти после запуска программы и ее последующего прерывания клавишей Ctrl+Break. В нашем случае новый поток запустился лишь после того, как счетчик в главном потоке увеличился до 341!



Содержание раздела