Почему метод IHTMLImgElement put_src возвращает E_OUTOFMEMORY при вызове из потока?

У меня есть BHO (расширение Internet Explorer), и я пытаюсь установить "data:image/png;base64, [code]" (буфер изображения с кодировкой base64) в качестве источника IHTMLImgElement. Когда put_src вызывался из основного потока BHO, проблем не было, но теперь, когда я вызываю его из другого потока, он возвращает E_OUTOFMEMORY. Строка в кодировке base64 очень длинная. Для более короткой строки base64 ошибка не возвращается.

Я должен указать, что у меня нет утечек памяти, я использовал только умные указатели COM и удалил всю выделенную память.

Также я использую тот же тип строки base64 для вызова set_backgroundImage для объектов IHTMLStyle, и он не возвращает ошибок.


person evilwhaleboy    schedule 03.03.2014    source источник
comment
Объект MSHTML Document и его DOM API не ориентированы на многопотоковое исполнение. Он должен вызываться в том же и единственном потоке, в котором он был создан, то есть в том же потоке, в котором создается ваш BHO.   -  person noseratio    schedule 03.03.2014
comment
Спасибо за ваш ответ. Что конкретно означает не потокобезопасность? Как я писал в основном посте, вызов set_backgroundImage возвращается без проблем.   -  person evilwhaleboy    schedule 03.03.2014
comment
Я использовал GIT (таблицу глобального интерфейса) для маршалинга и демаршалирования объекта IWebBrowser2, поэтому, насколько я понимаю, он должен работать нормально.   -  person evilwhaleboy    schedule 03.03.2014


Ответы (2)


Что конкретно означает «не потокобезопасный»? Как я писал в основном посте, вызов set_backgroundImage возвращается без проблем.

В данном контексте это просто означает, что вы не можете вызывать его напрямую из любого другого потока, кроме основного потока, в котором был создан ваш BHO. Если вам нужно использовать его из другого потока, маршалируйте интерфейс объекта IHTMLImgElement в этот поток, например. с CoMarshalInterThreadInterfaceInStream.

Больше информации:

person noseratio    schedule 03.03.2014
comment
Я использовал GIT (таблицу глобального интерфейса) для маршалинга и демаршалирования объекта IWebBrowser2. - person evilwhaleboy; 03.03.2014
comment
@evilwhaleboy, покажи код, который ты используешь для маршалинга COM-объектов WebBrowser/MSHTML через GIT. - person noseratio; 04.03.2014
comment
@evilwhaleboy, похоже, все в порядке. Вы случайно не кешируете какие-либо указатели COM между потоками, например указатель на IHTMLDocument2? - person noseratio; 04.03.2014
comment
извините за, возможно, глупый вопрос, но что означает кэширование указателя между потоками? - person evilwhaleboy; 04.03.2014
comment
Это означает, что вы можете сохранить указатель на COM-интерфейс в одном потоке (в члене или статической переменной), а затем использовать его в другом потоке без маршалинга. - person noseratio; 04.03.2014
comment
Я такого не делал. - person evilwhaleboy; 04.03.2014
comment
Я предполагаю, что ошибка E_OUTOFMEMORY связана с очень длинной строкой ~ 75000 символов. Но я не понимаю, почему он работает, когда он вызывается из основного потока, а не в рабочем потоке. - person evilwhaleboy; 04.03.2014
comment
@evilwhaleboy, вы можете попытаться передать этот вызов (и данные) в основной поток через свой собственный интерфейс в вашем BHO, а затем напрямую вызвать MSHTML в основном потоке. - person noseratio; 04.03.2014
comment
Я не думаю, что понимаю, что вы имеете в виду, мне нужно выполнить работу в потоке, как я могу вызвать метод в основном потоке? - person evilwhaleboy; 04.03.2014
comment
@evilwhaleboy, следуя образцу из первой ссылки в моем ответе. Он содержит TSTMARSH, реализующий интерфейс ITest, и показывает, как вызывать его из другого потока. Сделайте то же самое с вашим BHO. - person noseratio; 05.03.2014

Если объект IWebBrowser2 маршалируется в другой поток, строка, передаваемая методу put_src, должна быть BSTR, выделенной с помощью SysAllocString, а не простой LPWSTR. Получил ответ с другого форума.

person evilwhaleboy    schedule 06.03.2014