ПОНЯТНО О Visual Basic NET (том 3)

       

Потоки


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

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

 Создайте проект с тремя кнопками и двумя текстовыми полями. Вот код:

Dim Поток1 As New System.Threading.Thread(AddressOf Процесс_потока1)

Dim Поток2 As New System.Threading.Thread(AddressOf Процесс_потока2)

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Поток1.Start()

End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

        Поток2.Start()

End Sub

Private Sub Процесс_потока1()

        Dim i As Integer = 1



        Do

            TextBox1.Text = i

            Debug.WriteLine("Работает 1 поток:" & i)

            i += 1

        Loop

End Sub

Private Sub Процесс_потока2()

        Dim i As Integer = 1

        Do

            TextBox2.Text = i

            Debug.WriteLine("Работает 2 поток:" & i)

            i += 1

        Loop

End Sub

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

        MsgBox("Привет!")

End Sub

Пояснения: Вы придумали две процедуры: Процесс_потока1 и Процесс_потока2, которые хотите выделить в отдельные потоки. Первая из этих процедур бесконечно печатает возрастающие числа в текстовом поле 1 и в окне Output, вторая – в текстовом поле 2 и в окне Output.

Для организации потоков вы написали первые две строки кода:

Dim Поток1 As New System.Threading.Thread(AddressOf Процесс_потока1)


Dim Поток2 As New System.Threading.Thread(AddressOf Процесс_потока2)

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

Запустите проект. Щелкните по 1 кнопке. Выполнится метод Start объекта Поток1, запускающий поток. В текстовом поле 1 и окне Output побегут числа. Теперь нажмите на 3 кнопку. Она нажмется и, как положено, появится сообщение. Обратите внимание, что поток при этом не прервался, числа в поле и окне продолжают бежать. (Возможно, числа в окне Output отстают от чисел в текстовом поле.)

Закройте сообщение. Закройте крестиком форму. Обратите внимание, что числа в окне Output продолжают бежать. Кнопка Stop Debugging на панели Debug в виде черного квадратика не стала бледной. Это значит, что выполнение проекта закрытием формы не завершилось. Работа потока продолжается. Завершите проект и поток кнопкой Stop Debugging.

 Снова запустите проект. Щелкните по 1 кнопке. В текстовом поле 1 и окне Output побегут числа. Нажмите кнопку 2. Запустился 2 поток. Числа побежали теперь и в текстовом поле 2.  В окне Output вдобавок к числам от 1 потока побежали вперемежку с ними и числа от 2 потока (возможно, не сразу, а с задержкой в несколько секунд):

Работает 1 поток:22900

Работает 2 поток:31

Работает 1 поток:22901

Работает 2 поток:32

Работает 1 поток:22902

Работает 2 поток:33

Работает 1 поток:22903

Работает 1 поток:22904

Работает 2 поток:34

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

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



Однако, мы можем управлять приоритетом каждого из потоков. Если мы хотим, чтобы 2 поток выполнялся почаще по сравнению с 1 потоком, мы можем перед стартом 2 потока написать:

        Поток2.Priority = Threading.ThreadPriority.Highest

и соответственно перед стартом 1 потока:

        Поток1.Priority

= Threading.ThreadPriority.Lowest

Здесь мы выбрали самый высокий и самый низкий приоритеты. У перечисления ThreadPriority есть и промежуточные градации.

Теперь печать будет такая:

Работает 2 поток:758

Работает 2 поток:759

Работает 2 поток:760

Работает 2 поток:761

Работает 1 поток:212

Работает 2 поток:762

Работает 2 поток:763

Работает 1 поток:213

Работает 2 поток:764

Работает 2 поток:765

Работает 2 поток:766

Как видите, 2 поток выполняется чаще.

Вот несколько методов класса Thread, которые помогут вам управлять потоками:

Метод

Действие

Sleep (2000)

Пауза в работе потоков на 2 секунды. Метод статический.

Suspend

Приостановить работу потока

Resume

Возобновить работу потока

Abort

Прекратить работу потока


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