(NET) 2002

My first program in .NET framework

Здесь выложена моя САМАЯ ПЕРВАЯ и очень дорогая для меня прога на .NET, написанная летом 2002 года. Интересно вспомнить проблемы, с которыми я сталкивался столько лет назад...


Во-первых, теперь нет массивов элеменов управления - и приходится вручную корячится с именами полей на форме - это мне показалось самым неудобным нововведением в .NET Framework.

Во-вторых, возникла проблема взаимодействия среды .NET с унаследованными COM-обьектами через обертку INTEROP. Родной для COM-обьектов бейсик нормально открывает все методы у свойства в данном случае обьекта QueryTables (это запрос, который импортирует данные в таблицу Excel). Среда .NET не просто не видит этого интерфейса - она неправильно с ним работает! Иначе говоря выделенная текстовая строка должна свободно заменятся переменной path1 - однако при замене обертка COM-INTEROP падает! С другой стороны метод QueryTables.Add нельзя вызывать без параметров в принципе. Т.е. деклараций о совместимости очень много - но практически не получается...

В-третьих, я хотел сделать свою прогу многопоточной. Во-первых, понятно, что обращения к внешним страницам через HTTP будут происходить неопределенно долго (DNS, SQL-запросы, связь и пр.), поэтому надо делать их в дополнительном потоке (или нескольких). Во-вторых хотелось добавить в прогу асинхронную анимацию - типа как летают странички при копировании файлов Windows. В третьих, сайт у меня большой (около 10 тыс. страниц) и соотвественно, журналы, формируемые этой прогой огромные - мегабайт по 300. А значит в Excel они будут грузится по полчаса. Значит, автоматизация Office - третий поток. Поскольку раньше я без труда писал реентерабельные модули на ассемблере, я захотел разобратся в многопоточном программировании в .NET Framework. Т.е. для начала надо создать один поток, который независимо от работы основного потока будет монотонно рисовать на форме картинки, другой поток будет через HTTP дергать внешние файлы, третий поток будет потихоньку грузить созданные фрагменты журналов в Excel - ну а основной поток формы ведет журнал проверки сайта и никогда не должен подвиснуть...

На первом этапе я разобрался с доменами приложений - с классом AppDomain - в описании класса читаем, что этот класс является NotInheritable - что означает что его экземпляры создавать конструктором нельзя. Зато мы видим, что свойство CurrentDomain класса AppDomain является статическим, что означает - мы можем прямо привязыватся к этому полю непосредственно через класс, а не только через его экземпляр. Т.е. с учетом NotInheritable - только к классу, а не к экземпляру - вот так .

Процедурку SaveObject я создавал, чтобы выполнить SOAP-сериализацию обьектов - так были созданы Assemblies.xml и SetupInformation.xml. К сожалению, сериализируются лишь некоторые свойства обьектов, в чем можно убедится посмотрев на обьект AppDomain.SetupInformation непосредственно в отладчике. Поэтому в плане отладочного просмотра обьектов от этой процедуры проку оказалось мало.

Обьект AppDomain выглядит вот так. Как видно текущий ThreadID отлаживаемой программы Link_cheker - 1984, однако отладчик показывает ProcessID - 1724, кроме того есть процесс 1980 с высоким приоритетом - из этого видно что потоки .NET Framework не имеют отношения к процессам Windows. Кроме того очевидно, что процесс 1980 с высоким приоритетом - это и есть сам процесс отладчика

Далее я попробовал поработать с обьектом System.Threading.Thread. Как и следовало ожидать в однопоточном режиме, свойство GetDomain обьекта System.Threading.Thread.CurrentThread возвратило ссылку на тот же самый обьект, что и AppDomain.CurrentDomain. Свойство ApartmentState = "STA" что означает, что домен приложения работает в однопоточном режиме. Для этого я сделал вот так. Теперь потоков стало два и второй процесс показал многопоточность - MTA, но параллельной работы потоков не произошло (дополнительно порожденный процесс фактически отрабатывает только после основного), кроме того, основной процесс в ней так и остался однопоточным, кроме того стали падать операции с файлами.

Обращение к MSDN привело к пониманию, что все методы, свойства и события форм Windows небезопасны по отношению к дополнительным потокам, порожденным из основного потока формы. Поэтому чтобы что-то сделать в дополнительном потоке с формой, надо в нем вызвать метод Invoke (единственный, который безопасен по отношению к потокам). Этот метод выполняет заданный делегат в основном потоке формы. Фактически прога после этого стала такой. Теперь контексты потоков меняются прекрасно - прога наконец-то перестала падать, но тем не менее, даже несмотря но более высокий приоритет дополнительного потока (в данном запуске 2084), он получает управление только после завершения основного потока формы - 2036.

Этой фишки я так и не понял - ведь в основном потоке полно асинхронных операций ввода/вывода - почему за это время исполнительная среда .NET Framework не выполнила делегат, указанный в Invoke? В итоге пришлось просто закомментировать вызов потока анимации.

Модулю анимации помешала и еще одна фишка - понятно, что рисунки надо грузить из ресурс-файла, встроенного в исполняемый PE-модуль. Ну не выкладывать же фрагменты анимации отдельными файлами!. Для начала все рисунки проекта были обьявлены встроенными ресурсами и сам файл ресурсов тоже. Однако просмотр RESX-Файла показал, что сразу были встроены только ресурсы, используемые на форме. Это подтвердил и просмотр RESX-файла в браузере. Осталось непонятным - включил ли компилятор файл RESOURCES в EXE-модуль. В каталоге DEBUG - Файл RESOURCES был отдельно, а в каталоге BIN - его уже не было. PE-броузер показывал, что ресурсных рисунков нет в составе PE-модуля, но ILDASM - благополучно извлекал ресурсные рисунки командой DUMP. При этом сама студия показывала, что ресурсов нет в составе PE-модуля и предлагала их добавить вручную.

Как получить более внятный журнал компиляции? Я понял, что надо либо создать нормальный конфигурационный файл vbc.config.exe в каталоге C:\WINNT\Microsoft.NET\Framework\v1.0.3705 либо хотя бы в студии где-то задать параметр вызова компилятора /verbose - как это сделать - я так и не понял. В итоге вопрос - попал ли файл RESOURCES внутрь PE-модуля остался до конца не выясненным.

Теперь надо было попробовать прочитать ресурсные рисунки классами из пространства System.Resources. Класс ResoureManager подходит вполне, тем более сам дизайнер форм запаковал рисунки этим классом. Как оказалось, этим классом прочитался только тот рисунок, который вложил дизайнер форм - остальных рисунков в PE-файле судя по всему просто нет. Ну а делать так - это слишком коряво. Вот это собственно, вторая фишка, которая не позволила добавить в прогу анимацию...


Увы, с ресурсами и многопоточностью я разобрался только через пару лет после написания этой своей первой проги... И понял, что массивы элеменов управления все-таки поддерживаются (как и массивы с ненулевым началом)...



Comments ( )
Link to this page: //www.vb-net.com/Dotnet/Tour11/Index.htm
< THANKS ME>