Многопоточность в VB

Персональный блог одноименного форумчанина. Человека и парохода, не побоюсь этого сравнения :)

Модератор: tyomitch

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Многопоточность в VB

Сообщение tyomitch » 17.05.2006 (Ср) 11:31

Хочется развеять ряд распространённых заблуждений.

* VB6 поддерживает многопоточные программы. В частности, на VB можно -- безо всякого шаманства -- написать многопоточный COM-сервер (как в виде ActiveX EXE, так и в виде ActiveX DLL).

Для обеспечения этого рантайм написан исключительно multithreading-aware способом: все "глобальные" данные на самом деле хранятся в TLS. Отсутствие по-настоящему глобальных данных обеспечивает защиту от race-condition-ов и других ошибок синхронизации.


* Написать на VB6 многопоточную программу намного сложнее, чем просто вызвать CreateThread(AddressOf ThreadProc), проверить под IDE (работает! вот чудо!), откомпилировать в P-Code и сделать вид, что всё в порядке.

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

Поскольку скомпилированная в Native Code программа расчитывает обнаружить в TLS все свои "глобальные" данные, а нить, созданная по CreateThread, не содержит TLS, то такой наивный способ запустить новую нить в скомпилированном коде не работает.


* И всё же написать на VB6 нормальную многопоточную программу возможно: для этого придётся в лучших традициях процедуры bootstrap (поднятие себя за шнурки ботинков) из созданной нити инициализировать TLS вручную. (Код на VB не может работать без TLS; как же он сам создаст себе TLS? Оказывается, сможет.)

Такие трюки, однако, требуют большого геморроя c хитрым API, который непременно нужно объявлять в TLB -- иначе магия не сработает.


* Если многопоточное VB6-приложение написано правильно, то глобальных данных -- а значит, и способов обмена данными между нитями -- нет вовсе. Координация нитей в таком приложении сопряжена с большими сложностями. (Можно, например, использовать атомы: они глобальные для оконной станции.)

Можно использовать объектные вызовы между нитями, но это именно то, чего лучше избегать: при таком вызове вызывающая нить замораживается до освобождения вызываемой -- фактически, программа превращается обратно в однопоточную. Да и откуда во вновь созданной нити взять ссылку на объект из другой нити? Ведь передать её не в чем.


* Если у вас после всего сказанного осталось желание писать на VB6 многопоточную прогу -- подумайте ещё раз. Многопоточность -- не магия, которая решит за программиста вопросы проектирования программы. Если у вас зависает однопоточная программа, то зависнет и многопоточная.

Далее, есть много способов обойтись без многопоточности. В самом худшем случае, можно запустить новую нить в крохотном ассемблерном переходнике, который будет общаться с основной программой посылкой сообщений (см. Waiter от GSerg-а). Но часто удаётся решить проблему одновременного выполнения нескольких задач вовсе не выходя за рамки одной нити (см. мои посты про фиберы).
Изображение

Twister
Теоретик
Теоретик
Аватара пользователя
 
Сообщения: 2251
Зарегистрирован: 28.06.2005 (Вт) 12:32
Откуда: Алматы

Сообщение Twister » 25.06.2006 (Вс) 0:44

Нашел в сети статейку Appleman-а, может кому будет интересно почитать...
А я все практикую лечение травами...

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 25.06.2006 (Вс) 13:12

Twister, ты осознаёшь, что эта статья -- про VB5, и далеко не целиком применима к VB6?
Изображение

Twister
Теоретик
Теоретик
Аватара пользователя
 
Сообщения: 2251
Зарегистрирован: 28.06.2005 (Вт) 12:32
Откуда: Алматы

Сообщение Twister » 25.06.2006 (Вс) 13:32

Сознаю. Но думаю кое-что полезное почерпнуть из нее можно...
А я все практикую лечение травами...

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 11.07.2006 (Вт) 14:47

Поскольку скомпилированная в Native Code программа расчитывает обнаружить в TLS все свои "глобальные" данные, а нить, созданная по CreateThread, не содержит TLS, то такой наивный способ запустить новую нить в скомпилированном коде не работает.
Я не могу понять, на основе чего создалось мнение, что обычная EXE-программа на VB хранит глобальные переменные в TLS?
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 11.07.2006 (Вт) 15:12

На основе заглядывания внутрь.
Хочешь -- перепроверь.
Изображение

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 11.07.2006 (Вт) 16:08

Тогда можно попорядку и "для чайников", как такое заглядывание внутрь можно организовать? Вот, скажем, в этом проекте идет обращение к глобальной переменной A... Но где там что-то касающееся TLS?
http://danasoft.ru/users/andll/for_tyomitch.zip
Чего не прикрепляются вложения? Права недонастроили?
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 11.07.2006 (Вт) 19:33

Про права -- это к RayShade.
Про глобальные переменные -- поставь в своём любимом отладчике брякпойнт на TlsSetValue, и посмотри, сколько раз она вызовется. У меня вызвалась 22 раза.
Изображение

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 11.07.2006 (Вт) 21:14

и? Из того что он где-то вызывается еще не следует, что глоабальные переменные хранться в TLS, разве нет?
Поставь брейкпоинт на A=5 (проект компилировался с Debug symbols).
И ты увидиш, что в компиляции этой команды нету обрашения к системным функциям вообще.
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 12.07.2006 (Ср) 10:12

[edit]софистика оказалась излишней[/edit]
Последний раз редактировалось tyomitch 14.07.2006 (Пт) 9:51, всего редактировалось 1 раз.
Изображение

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 12.07.2006 (Ср) 11:34

Хорошо. Что, по-твоему, хранится в TLS? очевидно, какие-то переменные.
В однопоточной проге они глобальные. Значит, в TLS хранятся глобальные переменные

Я полагает, нелишне напомнить, что мир устроен так как он устроен, а не так как он ДОЛЖЕН быть устроен.
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 12.07.2006 (Ср) 11:46

Хорошо. Что, по-твоему, хранится в TLS?
Изображение

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.07.2006 (Пт) 9:48

Проверил детально. Публичные переменные модулей лежат не в TLS.

Однако, все стандартные функции рантайма (за небольшим исключением) пользуются TLS. В частности, им пользуется механизм обработки исключений, так что любая команда, потенциально способная вызвать исключение, неявно использует TLS.

Т.е. по сути я всё же прав: без TLS ничего не заработает.


--------------------
Кстати:
ANDLL писал(а):
Поскольку скомпилированная в Native Code программа расчитывает обнаружить в TLS все свои "глобальные" данные, а нить, созданная по CreateThread, не содержит TLS, то такой наивный способ запустить новую нить в скомпилированном коде не работает.
Я не могу понять, на основе чего создалось мнение, что обычная EXE-программа на VB хранит глобальные переменные в TLS?

Я не могу понять, на основе чего создалось мнение, что "глобальные данные" программы -- это именно публичные переменные её модулей?
Изображение

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 14.07.2006 (Пт) 10:59

А что, публичные переменные не являются глобальными данными? :)
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.07.2006 (Пт) 11:41

А что, глобальные данные исчерпываются публичными переменными? :-)
Изображение

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 14.07.2006 (Пт) 13:53

Не исчерпываются:)
tyomitch писал(а):все "глобальные" данные на самом деле хранятся в TLS
Однако же все как раз там и не храняться...
Я имел ввиду это.
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог


Вернуться в Tyomitch

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6

    TopList