Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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.062 c
2-1171880785
sergeyst
2007-02-19 13:26
2007.03.11
Редактирование записей БД


2-1171953044
Sapos
2007-02-20 09:30
2007.03.11
Как вернуть путь к папке в которой установлена ОС?


2-1171859755
XDISABLED
2007-02-19 07:35
2007.03.11
Edit


2-1171959306
vitv
2007-02-20 11:15
2007.03.11
DBGrid11CellClick(Column: TColumn);-вопрос реализации


2-1171896060
Ezorcist
2007-02-19 17:41
2007.03.11
Удалить первые N байт из MemoryStream?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский