C# IE BHO: работать асинхронно, сохраняя при этом один и тот же поток?

У меня есть IE BHO, который находится в разработке на C#. Предполагается, что пользователь должен что-то сделать, связаться с нашим сервером и загрузить некоторые данные, а затем изменить DOM текущей загруженной веб-страницы с результатами.

Я сталкиваюсь с некоторыми, казалось бы, непреодолимыми проблемами, связанными с правилами разделения и многопоточности COM, а именно, я не могу получить доступ к IE DOMDocument за пределами текущего потока, и я не могу придумать какой-либо способ запустить что-то асинхронно без блокировки до IE, пока он не будет закончен.

Моя первая попытка заключалась в том, что фоновая связь с сервером выполнялась в зависимости от событий: моя программа инициировала связь из события mshtml (например, BeforeNaviagate2 или DocumentComplete) и отправляла результаты из отдельного обработчика событий. срабатывает объект связи с сервером, когда он заканчивает свою работу.

Этот метод отлично работал в быстром симуляторе, который я собрал (всего лишь простое приложение с элементом управления WebBrowser), но в IE он выдавал исключение COM, потому что я пытался изменить DOM страницы через отдельный поток.

Поэтому я попытался сохранить все в одной и той же функции и заставить свой код ждать, пока объект связи с сервером выполнит свою работу с помощью цикла while, например:


    int waited = 0;
    while (!OurServerCommRequest.ready) {
        System.Threading.Thread.Sleep(1);
        Application.DoEvents();
        waited++;

        if (waited > constants.TIMEOUT_OURSERVER_REQUEST) {
            log.wL("Timed out");
        }

    }

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

Первоначально я хотел начать обработку, как только URL-адрес будет доступен (через событие NavigationComplete2), но я обнаружил, что ожидание, когда тег ‹body> станет доступным, если связь с моим сервером завершится до загрузки страницы пользователя, также заблокирует IE — выброс это в бесконечный цикл, в то время как мой код ожидает тела HTML, в то время как страница не может обновить себя, чтобы выполнить вышеупомянутый цикл.

Я думал о том, чтобы переместить все это в javascript страницы фактического пользователя, но кажется, что тем самым я открываю банку червей в борьбе с проблемами безопасности XSS.

Итак... мой вопрос таков: возможно ли асинхронно запускать код в C# IE BHO, сохраняя при этом возможность манипулировать DOM страницы пользователя? Я поспрашивал некоторых друзей, и большинство людей говорят мне, что это маловероятно. Я все еще новичок в COM и C #, пришедший из C/VB.net/JS/AS.

Спасибо!

-Том


person Tom Corelis    schedule 22.04.2009    source источник
comment
Том, ты когда-нибудь заставлял это работать? Если да, то есть ли у вас пример кода? Я работаю над аналогичной проблемой и не могу найти способ сохранить асинхронность. В качестве обходного пути я сделал то, что вы описали выше (цикл while), но это неприемлемо. Спасибо.   -  person    schedule 22.12.2010
comment
Прошло некоторое время с тех пор, как я работал над этим проектом, но я считаю, что проблема была решена путем вращения запроса сервера в другой поток, а затем прямо перед тем, как он изменяет DOM, переключаясь на основной поток IE. Это позволило избежать нарушения и внедрить наш код в DOM страницы, не прерывая пользователя. Подробности о переходе между потоками можно найти здесь: stackoverflow.com/questions/2367718/   -  person Tom Corelis    schedule 03.01.2011


Ответы (1)


Вам нужно маршалировать объект DOM из потока, в котором он был создан, в ваш рабочий поток. Здесь очень подробно рассказывается о совместной работе COM и C#.

Все объекты IE DOM являются объектами STA.

person i_am_jorf    schedule 23.04.2009