Форум: "Corba";
Текущий архив: 2007.03.11;
Скачать: [xml.tar.bz2];
ВнизDCOM. Работа с объектами в потоках. Найти похожие ветки
← →
Артем Кудлаенко © (2005-10-22 16:57) [0]Создаю два объекта на 2-х удаленных машинах.
В первом потоке вызываю метод первого объекта, во втором - второго.
Все это в потоках для того, чтобы не ждать завершения работы методов, т.е. выполнять методы параллельно. Все это не работает без синхронизации, а с использованием синхронизации методы выполняются последовательно.
Что можно сделать для того, чтобы работа с методами выполнялась параллельно?
← →
Артем Кудлаенко © (2005-10-22 17:09) [1]Уточню.
Создается по одному объекту на машину.
С синхронизацией видно в закладке Сеть Диспетчера задач Windows, что данные передаются и получаются. Я передаю массив с 2 000 000 элементов по этому передачу данных легко видеть на графике.
Без синхронизации создается эффект, как будто вызов метода пропускается.
← →
Набережных С. © (2005-10-23 17:33) [2]Ни-и-и-че не понял:((
Попробую догадаться. "с использованием синхронизации" - это, по-видимому, Synchronize. В этом случае просто сам вызов метода интерфейса происходит в основном потоке. Чтобы напрямую вызывать из "дополнительных" апартаментов(в данном случае, видимо, именно это имеет место быть), необходимо интерфейсы туда маршалировать, а не просто передать ссылку.
См. пары
CoMarshalInterThreadInterfaceInStream(CoMarshalInterface)
+
CoGetInterfaceAndReleaseStream(CoUnmarshalInterface)
И про CoInitialize/CoUninitialize не забудь.
← →
Набережных С. © (2005-10-23 18:09) [3]Если моя догадка верна, то, пожалуй, вместо вышеуказанных функций удобней использовать следующее(или как пример):
unit StdGlobalInterfaceTable;
interface
uses
ActiveX;
const
CLSID_StdGlobalInterfaceTable: TGUID = "{00000323-0000-0000-C000-000000000046}";
function GitMarshal(const IID: TGUID; const Obj: IUnknown; out Cookie: Cardinal): HResult; stdcall;
function GitUnmarshal(Cookie: Cardinal; const IID: TGUID; out Obj): HResult; stdcall;
function GitRevoke(Cookie: Cardinal): HResult; stdcall;
function AllocStdGit(): HResult; stdcall;
implementation
var
IGit: IGlobalInterfaceTable = nil;
function AllocStdGit(): HResult;
begin
if Assigned(IGit) then Result:=S_OK else
Result:=CoCreateInstance(
CLSID_StdGlobalInterfaceTable, nil, CLSCTX_INPROC_SERVER,
IGlobalInterfaceTable, IGit)
end;
function GitMarshal(const IID: TGUID; const Obj: IUnknown; out Cookie: Cardinal): HResult; stdcall;
begin
if Assigned(IGit) then
Result:=IGit.RegisterInterfaceInGlobal(Obj, IID, Cookie)
else
Result:=E_UNEXPECTED;
end;
function GitUnmarshal(Cookie: Cardinal; const IID: TGUID; out Obj): HResult; stdcall;
begin
if Assigned(IGit) then
Result:=IGit.GetInterfaceFromGlobal(Cookie, IID, Obj)
else
Result:=E_UNEXPECTED;
end;
function GitRevoke(Cookie: Cardinal): HResult; stdcall;
begin
if Assigned(IGit) then
Result:=IGit.RevokeInterfaceFromGlobal(Cookie)
else
Result:=E_UNEXPECTED;
end;
end.
Но проверял я это только в W2k and WinXP.
← →
Артем Кудлаенко © (2005-10-24 17:04) [4]
> function GitRevoke(Cookie: Cardinal): HResult; stdcall;
заменил на
function GitRevoke(Cookie: TGUID): HResult; stdcall;
Была ошибка Icompatible types "TGUID" and "Cardinal".
И вопрос: как мне использовать Ваш пример?
Примерно так:
1. В начале я вызываю:
AllocStdGit();
2. Затем
GitMarshal(IID, Obj, Cookie)
и передаю параметры:
IID - GUID своего интерфейса ICalc
Obj - саму ссылку на Calc типа ICalc
Cookie - переменная, которая будет содержать некий Cookie.
> Чтобы напрямую вызывать из "дополнительных" апартаментов(в
> данном случае, видимо, именно это имеет место быть), необходимо
> интерфейсы туда маршалировать
Я так понимаю, эта функция именно это и делает? И вместо того кода, который передает ссылку на com-объект в поток, что мне необходимо сделать?
В общем, пожалуйста, поподробнее.
← →
Набережных С. © (2005-10-24 19:26) [5]
> Артем Кудлаенко © (24.10.05 17:04) [4]
>
> > function GitRevoke(Cookie: Cardinal): HResult; stdcall;
>
>
> заменил на
>
> function GitRevoke(Cookie: TGUID): HResult; stdcall;
> Была ошибка Icompatible types "TGUID" and "Cardinal".
Э-э-э... чево? :)) Ты, брат, откуда берешь декларацию IGlobalInterfaceTable?
Никаких ошибок быть не должно, код неоднократно проверен.
Вот такая декларация правильная(ActiveX.pas, D7):
IGlobalInterfaceTable = interface(IUnknown)
["{00000146-0000-0000-C000-000000000046}"]
function RegisterInterfaceInGlobal(const pUnk: IUnknown; const riid: TIID;
out dwCookie: DWORD): HResult; stdcall;
function RevokeInterfaceFromGlobal(dwCookie: DWORD): HResult; stdcall;
function GetInterfaceFromGlobal(dwCookie: DWORD; const riid: TIID;
out ppv): HResult; stdcall;
end;
Она соответствует описанию в MSDN, в СИ-шных заголовках и реальности:)
P.S. Нельзя же так - чуть до удара старика не довел:)))
> 1. В начале я вызываю:
>
> AllocStdGit();
>
> 2. Затем
>
> GitMarshal(IID, Obj, Cookie)
>
> и передаю параметры:
> IID - GUID своего интерфейса ICalc
> Obj - саму ссылку на Calc типа ICalc
> Cookie - переменная, которая будет содержать некий Cookie.
>
Все правильно.
> Я так понимаю, эта функция именно это и делает? И вместо
> того кода, который передает ссылку на com-объект в поток,
> что мне необходимо сделать?
А вот этот полученный кук и передать в поток(например, через конструктор потока). Это - идентификатор сохраненной в GIT маршалированной интерфейсной ссылки. Потом поток может вызвать GitUnmarshal, передав в него этот кук, и получить тот самый маршалированный тобой ICalc, но уже демаршалированный в апартамент этого потока. Вызов в Execute потокa может выглядеть так:
var
Calc: ICalcж
begin
CoInitialize(nil);
try
if S_OK = GitUnmarshal(FCookie, ICalc, Calc) then
begin
// Теперь с интерфейсом можно работать
Calc.MyMethod1;
Calc.MyMethod2;
....
end;
finally
CoUninitialize;
end;
end;
Ну а когда больше не нужно будет хранить данный экзэмпляр ICalc in GIT, следует вызвать GitRevoke опять с тем же куком, после чего значение этого кука станет недействительным, а пакет с маршалированным экзэмпляром ICalc будет удален из GIT.
← →
Артем Кудлаенко © (2005-10-25 20:48) [6]Большое человеческое спасибо за пример.
В Delphi 7 все в порядке.
А вот как выглядит декларация этого интерфейса в Delphi 6:
IGlobalInterfaceTable = interface(IUnknown)
["{00000146-0000-0000-C000-000000000046}"]
function RegisterInterfaceInGlobal(const pUnk: IUnknown; const riid: TIID;
out dwCookie: DWORD): HResult; stdcall;
function RevokeInterfaceFromGlobal(const riid: TIID): HResult; stdcall;
function GetInterfaceFromGlobal(dwCookie: DWORD; const riid: TIID;
out ppv): HResult; stdcall;
end;
← →
Набережных С. © (2005-10-27 22:00) [7]
> А вот как выглядит декларация этого интерфейса в Delphi
> 6
Не обращай вниманания - брехня!
← →
Артем Кудлаенко © (2005-10-28 23:10) [8]
> Не обращай вниманания - брехня!
В смысле? :)
← →
Набережных С. © (2005-10-29 06:43) [9]
> Артем Кудлаенко © (28.10.05 23:10) [8]
В том смысле, что в D6 декларация неправильная, а в D7 ее исправили.
Страницы: 1 вся ветка
Форум: "Corba";
Текущий архив: 2007.03.11;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.042 c