Потоки
Проблема в том, чтобы заставить обе процедуры работать одновременно. Решается она организацией так называемых потоков. Если вы хотите, чтобы некая процедура позволяла остальным частям проекта работать одновременно с ней и реагировать на события независимо от нее, вы выделяете ее в поток. Процесс выполнения процедуры при этом становится во многих отношениях независимым от выполнения остальной части проекта.
Свой поток вы можете организовать для любой процедуры. Получится многопоточный проект. Рассмотрим пример.
Создайте проект с тремя кнопками и двумя текстовыми полями. Вот код:
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 |
Прекратить работу потока |