Текущий архив: 2002.03.28;
Скачать: CL | DM;
ВнизДоспуп к свойтвам Internet Explorer (СОМ) при работе с SHTTP, а работа с СОМ при использовании потоков Найти похожие ветки
← →
Ramid (2002-01-16 13:37) [0]Проблема заключается в следующем:
1. Создается СОМ обьект: IE5
var v: variant;
V := CreateOleObject("InternetExplorer.Application.1");
V.Visible := Vis;
V.Navigate(open_url);
2. Получем доступ к его методам, может загружать страницы, проводить их разбор,
V.document.script.window.document.title;
4. Проблема 1 Невозможно обрататся к обьекту V из потока, выдает ошибку, обращение из синхронизированого потока к внешнему или еще что похлеще.
3. Проблемма 2 заключается при просмотре страницы SecureHTTP
в этом случае не доступа с V.document.script.window.document можно как нибудь это обойти и получить содержимое страниы?
ведь браузер показывает страницу и значит знает ее содержимое :)
← →
Digitman (2002-01-16 14:33) [1]Проблема 1 решается так:
CoInitialize(nil)// обязательно при обращении к механизму OLE/COM из потока !!
...
try
...
V := CreateOleObject("InternetExplorer.Application.1");
V.Visible := Vis;
V.Navigate(open_url);
...
finally
CoUninitialize; // обязательно при обращении к механизму OLE/COM из потока !!
...
end;
...
← →
Ramid (2002-01-16 16:14) [2]Да спасибо все получилось,
я тоже использовал CoInitialize(nil), но
СОМ создавался вне потока и до него,
при этом все равно выводится ошибка "EOleSysError:Приложении обратмлось к интерфейсу относящемуся к другому потоку"
Вот это можно как-нибудь обойти.
И если можно поподробнее что CoInitialize делает.
← →
Digitman (2002-01-16 17:01) [3]"СОМ создавался вне потока и до него" - этого не может быть) На основании чего ты сделал такое умозаключение ?
CoInitialize делает то, что написано в Delphi Win32 SDK help. Ты туда сходил, прежде чем спрашивать об этом ?
← →
Ramid (2002-01-16 17:16) [4]пример когда выдает ошибку:
procedure TForm1.SpeedButton2Click(Sender: TObject);
// отдельно создается обект
begin
V := CreateOleObject("InternetExplorer.Application.1");
V.Visible := true;
end;
после этого создается поток и запускается на выполнение
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
SecondProcess := TSub.Create(false);
end;
и если этому потоку принадлежит функция
procedure TSub.Execute;
begin
CoInitialize(nil);
try
form1.label2.caption := V.Visible; // выдается ошибка
finally
CoUninitialize();
Suspend();
Terminate();
Destroy();
end;
end;
можно ли этого избежать.
На счет Delphi Win32 SDK help мои извениения действительно не читал, прости, что отнял у тебя немного времени.
← →
Digitman (2002-01-16 17:52) [5]>> пример когда выдает ошибку:
procedure TForm1.SpeedButton2Click(Sender: TObject);
>> // отдельно создается обект
// в ОСНОВНОМ ПОТОКЕ он создается - это ты понимаешь ?
begin
V := CreateOleObject("InternetExplorer.Application.1");
V.Visible := true;
end;
>> после этого создается поток и запускается на выполнение
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
SecondProcess := TSub.Create(false);
end;
>> и если этому потоку принадлежит функция
// не ПОТОКУ ПРИНАДЛЕЖИТ ФУНКЦИЯ, а ОБЪЕКТ-ПОТОК реализует метод EXECUTE
procedure TSub.Execute;
begin
CoInitialize(nil); // это зачем ? разве OLE-объект создается в доп.потоке ??
try
form1.label2.caption := V.Visible; // выдается ошибка
// 1. ошибка ?? ну, разумеется !! асинхронные обращение к объектам-наследникам TWinControl из доп.потоков недопустимы !!
// на то есть метод TThread.Synchronize()
// 2. объект V создан в осн.потоке, а манипулируешь им в другом доп.потоке. Для объекта IE.Application это недопустимо, как и для многих распространенных OLE-серверов от MS (имеющих ThreadingModel = Apartment)
finally
CoUninitialize(); // а это зачем ?
Suspend(); // а здесь что делаешь ?
Terminate(); // а здесь ?
Destroy(); // а здесь ?
// комментируй свои мысли. полным-полно несуразиц в этих 3-х строчках
end;
end;
← →
Digitman (2002-01-16 17:55) [6]>> пример когда выдает ошибку:
procedure TForm1.SpeedButton2Click(Sender: TObject);
>> // отдельно создается обект
// в ОСНОВНОМ ПОТОКЕ он создается - это ты понимаешь ?
begin
V := CreateOleObject("InternetExplorer.Application.1");
V.Visible := true;
end;
>> после этого создается поток и запускается на выполнение
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
SecondProcess := TSub.Create(false);
end;
>> и если этому потоку принадлежит функция
// не ПОТОКУ ПРИНАДЛЕЖИТ ФУНКЦИЯ, а ОБЪЕКТ-ПОТОК реализует метод EXECUTE
procedure TSub.Execute;
begin
CoInitialize(nil); // это зачем ? разве OLE-объект создается в доп.потоке ??
try
form1.label2.caption := V.Visible; // выдается ошибка
// 1. ошибка ?? ну, разумеется !! асинхронные обращение к объектам-наследникам TWinControl из доп.потоков недопустимы !!
// на то есть метод TThread.Synchronize()
// 2. объект V создан в осн.потоке, а манипулируешь им в другом доп.потоке. Для объекта IE.Application это недопустимо, как и для многих распространенных OLE-серверов от MS (имеющих ThreadingModel = Apartment)
finally
CoUninitialize(); // а это зачем ?
Suspend(); // а здесь что делаешь ?
Terminate(); // а здесь ?
Destroy(); // а здесь ?
// комментируй свои мысли. полным-полно несуразиц в этих 3-х строчках
end;
end;
← →
Ramid (2002-01-16 18:21) [7]постой, неругай все сразу :)
да я понимаю что обьект TThread создается в основном потоке.
теперь давай посмотрим такой случай
procedure TSubmit.Execute;
begin
Synchronize(PrintTime);
end;
где
procedure TSubmit.PrintTime();
begin
form1.label2.caption := V.Visible; // генегирует исключение
//EOleSysError: Не удается выполнить выполнить исходящий вызов
//так как выполняется входящий синхроный вызов
end;
теперь на счет
Suspend(); // приостанавливается поток
Terminate(); // дается запрос на его прекращение
← →
Digitman (2002-01-16 18:38) [8]1. при чем здесь поток, в котором создается TThread ? Здесь важно совсем другое : OLE-объекты, созданные производителем в атрибутом Apartment, допускают обращение к их св-вам/методам лишь в том потоке, в котором они создаются !
2. form1.label2.caption := V.Visible
Нет желания вдаваться в подробности интерфейса объекта IE.App, но, imho, св-во IE.App.Visible д.иметь тип Boolean, в то время как TLabel.Caption - строковое св-во. Что на это скажешь ?
3. Suspend(); // приостанавливается поток
а кто, когда и в каком месте кода в каком потоке его возобновляет после самоприостановки по Suspend ? Ведь следующая строчка никогда не выполнится, если внешний по отношению к приостановленному поток не возобновит его вызовом метода Resume()
Terminate(); // дается запрос на его прекращение
кому - запрос ? поток запрашивает прекращение самого себя ? нонсенс ! Читай внимательно хэлп на этот метод и вникай в его реализацию в модуле classes.
← →
Ramid (2002-01-16 19:09) [9]На счет Terminate(); как мне тогда завершить поток когда он закончил работу которую должен был сделать?
form1.label2.caption := V.Visible - ничего страшного boolean - перечисляемый тип
type boolean = (false,true);
P.S. не суди строго за незнание чего либо, все когда то узнаешь впервые
← →
kig (2002-01-16 19:31) [10]Если хотите использовать в потоке (например Б) COM-объект, созданный в другом потоке (А), и объект не ThreadingModel != Free (Both), необходимо проделать примерно следующее:
1. в потоке Б вызвать CoInitialize (или CoInitializeEx)
2. в потоке А выполнить
CoMarshalInterThreadInterfaceInStream
Marshals an interface pointer from one thread to another thread in the same process.
HRESULT CoMarshalInterThreadInterfaceInStream(
REFIID riid, //Reference to the identifier of the interface
LPUNKNOWN pUnk, //Pointer to the interface to be marshaled
LPSTREAM * ppStm //Address of output variable that receives the
// IStream interface pointer for the marshaled
// interface
);
например CoMarshalInterThreadInterfaceInStream(WebBrowser.Document)
3. В потоке Б выполнить
Забрать ppStm и использовать его в
CoGetInterfaceAndReleaseStream
Unmarshals a buffer containing an interface pointer and releases the stream when an interface pointer has been marshaled from another thread to the calling thread.
HRESULT CoGetInterfaceAndReleaseStream(
LPSTREAM pStm, //Pointer to the stream from which the object is
// to be marshaled
REFIID riid, //Reference to the identifier of the interface
LPVOID * ppv //Address of output variable that receives the
// interface pointer requested in riid
);
Затем пользовать ppv (как WebBrowser.Document)
4. В потоке Б перед окончание вызвать CoUninitialize
Читать лучше первоисточники ))
MSDN
Platform SDK
Component service
COM
← →
Digitman (2002-01-17 13:34) [11]>Ramid
1. Не надо никаких вызовов метода Terminate() в твоей реализации метода Execute() - реализовано сквозное безусловное выполнение кода, циклы никакие не используются и с завершением работы метода завершается (ну, с некоторой долей условности - см.реализацию класса TThread в модуле classes) и сам отработавший поток как объект ОС.
А для того, чтобы был автоматически разрушен и поток как VCL-объект (тот самый созданный тобой экземпляр класса TSubmit), достаточно сделать так :
TSubmit = class(TThread)
...
public
...
constructor Create(CreateSuspended: Boolean);
...
end;
constructor TSubmit.Create(CreateSuspended: Boolean);
begin
inherited Create(True); // создаем приостановленный поток
...
// взводим флаг автоматич.разрушения экземпляра после завершения создаваемого им потока как объекта ОС
FreeOnTerminate:= True;
...
// если параметр конструктора был True - стартуем поток немедленно
if CreateSuspended then Resume;
end;
2. Перечислимый тип никак не соответствует строковому типу : первый относится к семейству Ordinal-типов, второй - к литерным типам. Необходимо явное преобразование наподобие следующего :
with form1.label2 do
if V.Visible then
Caption := "true"
else
Caption := "false"
Азы Паскаля !! А ты COM-объектами занялся ...
← →
Ramid (2002-01-17 16:25) [12]На счет СОМ с тобой спорить не буду, ты тут без сомнения лучше меня все знаешь, и я благодарен твоим советам.
← →
Digitman (2002-01-17 17:23) [13]>Ramid
Ну, разберись хоть с семействами типов Паскаля и их совместимостью. Ведь грубые ошибки делаешь, ну в самом деле !
Страницы: 1 вся ветка
Текущий архив: 2002.03.28;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.006 c