Многопотоковость в Visual Basic (исходники)

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

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

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

Дело в том, что АПИ функции - потоко-безопасные, и среди их многообразия найдутся достойные заменители стандартных VB-функций, в частности, вместо MsgBox можно использовать - MessageBox или MessageBoxEx. К сожалению об этом начинающие исследователи многопоточности VB еще не знают. Итак, в теле потока не работают множество стандартных функций VB. Мне известно, что это MsgBox и функции обработки строк, кроме UCase и LCase. Следующий момент - выход из потока. Я долго не мог понять, что происходит, и допускал те самые ошибки, о которых уже написал. Отказавшись от экспериментов я стал анализировать код Филлипа Вейдмана и обнаружил, что у него не предусмотрен выход из потока вообще, т.е. там стоит тупой вечный цикл. Зациклив свой пример, я перестал видеть эту ужасную ошибку о недопустимой операции, но, к сожалению, оказалось, что мои потоки с вечными циклами продолжают болтаться в памяти, в списках процессов, даже несмотря на то, что основная форма уже выгружена.

Пришлось читать MSDN по сабжу. Среди всяких интересных функций мне приглянулась TerminateThread, наверное своим бескомпромиссным Terminate. Поставив ее в конец своей потоковой функции, я наконец таки добился более-менее корректного выхода из потока. Но. Теперь обнаружилось, что если закрывать основную форму - опять вылетает эта ошибка о недопустимой операции!! Прокричав гневные ругательства в адрес всех разработчиков и идеологов VB, я скопировал удачное решение завершения потока в завершение работы формы в Form_Unload. Все заработало.

Пример который я делал был предназначен для демонстрации работоспособности "принципа пяти окон", предложенного Lamer’ом, при обсуждении неубиваемой программы в одной из тем на самом первом форуме. Поэтому, в нем кроме работы потоков присутствуют и синхронизация при помощи мьютексов и запуск приложений при помощи АПИ CreateProcess. Но все же основной лейтмотив - работа с потоками и лавирование между несовершенством механизмов VB при работе с ними. Вдумчивый читатель, надеюсь, без труда вникнет в эти тонкости и сделает соответствующие выводы, о том где уместно использовать VB, а где более подходящие языки программирования.

Напоследок хочу добавить о функции TerminateThread. Ее работа немного различна на различных платформах. К примеру в NT, перед вызовом этой функции необходимо закрыть все дескрипторы, и открытые файлы. Иначе они так и останутся открытыми, система их не будет закрывать, а это влечет за собой нерациональное использование ресурсов. Об этом и о многом другом можно узнать из MSDN. З.Ы. Пример нужно откомпилировать и запускать только откомпилированным. Как он работает: приложение создает мьютекс и запускает поток. Поток пытается завладеть мьютексом и в случае удачи каждые 600 миллисекунд просматривает список процессов. В них он пытается найти себя и считает количество своих копий. Если их меньше 5 то запускает сам себя. Если пытаться остановить выполнение активной программы, то мьютекс освобождается и им пытаются овладеть другие копии приложения. Овладев им история повторяется. Чтобы остановить этот беспредел нужно остановить потоки на всех неактивных копиях, ожидающих освобождения мьютекса воспользовавшись кнопкой на форме "Остановить поток". После этого остановить или выгрузить активное приложение.

Желаю удачи в изучении многопоточности.

 


Страница сайта http://silicontaiga.ru
Оригинал находится по адресу http://silicontaiga.ru/home.asp?artId=4761