Модераторы: MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема передачи множества функций в поток, Эффктивно ли решение? 
:(
    Опции темы
Caduser
Дата 24.1.2007, 02:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 2.10.2006
Где: г. Хабаровск

Репутация: нет
Всего: 1



Есть множество некоторых функций сервера приложений которые вызываются в клиенте так:
Код

CDS1.Data := DCOM.AppServer.Func1;
CDS2.Data := DCOM.AppServer.Func2;
CDS3.Data := DCOM.AppServer.Func3;
// и так далее, всего более 100 различных функций

необходимо поместить вызов этих функций в поток, как это сделать?
Пробовал так:
Поместить объект DCOM в поток очень просто:
Код

type
  TAppThread = class(TThread)
  private
    { Private declarations }
    DCOM: TDCOMConnection;
    FstFuncName: string;
  protected
    procedure Execute; override;
  public
    constructor Create;
    destructor  Destory;
  end;

implementation

{ AppThread }

constructor TAppThread.Create;
begin
  inherited Create(True);
  DCOM := TDCOMConnection.Create(nil);
  DCOM.ServerGUID := '{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}';
  DCOM.ComputerName := 'COMP01';
  DCOM.Open;
  FreeOnTerminate := false;
end;

destructor TAppThread.Destory;
begin
  DCOM.Close;
  DCOM.Free;
end;

procedure TAppThread.Execute;
begin
  { Place thread code here }
  if FstNameFunc='Func1' then
    DCOM.AppServer.Func1
  else
  if FstNameFunc='Func2' then
    DCOM.AppServer.Func2
  else
  if FstNameFunc='Func3' then
    DCOM.AppServer.Func3;
end;


initialization
  CoInitializeEx(NIL, COINIT_MULTITHREADED);
finalization
  CoUninitialize;

затем из основной программы:
Код

procedure Func1;
// это обертка функции Func1
begin
  MyThread.FstNameFunc:='Func1';
  MyThread.Resume;
end;

procedure Func2;
// это обертка функции Func2
begin
  MyThread.FstNameFunc:='Func2';
  MyThread.Resume;
end;
// и т.д.

Однако этот способ не эффективен т.к.: 
1. будет замедлять скорость вызова пропорционально увеличению числа функций. 
2. ситуация усложняется тем, что разным функциям нужно передавать различные параметры (например: DCOM.AppServer.Func5(par1, par2, par3);
Прошу помощи в поиске эффективного решения (например с помощью переменной вариантного типа)???

Это сообщение отредактировал(а) Caduser - 24.1.2007, 02:55
PM MAIL ICQ   Вверх
CatATonik
Дата 24.1.2007, 09:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 12.1.2007
Где: Москва

Репутация: 2
Всего: 8



Единственное универсальное решение которое приходит мне в голову, это передавать потоку название функции и список параметров, в виде вариантного массива, затем вызывать соответствующую функцию через IDispatch.Invoke.
Гемморойно, зато универсально.
PM MAIL   Вверх
Caduser
Дата 24.1.2007, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 2.10.2006
Где: г. Хабаровск

Репутация: нет
Всего: 1



Цитата(CatATonik @ 24.1.2007,  09:29)
Единственное универсальное решение которое приходит мне в голову, это передавать потоку название функции и список параметров, в виде вариантного массива, затем вызывать соответствующую функцию через IDispatch.Invoke.
Гемморойно, зато универсально.

пусть геморойно, мне важно чтоб скорость вызова функции снизилось не значительно. 
IDispatch.Invoke А можно хотябы приблизительно накидать, как это будет выглядеть?
Может как то так?
Код

var
  Disp:IDispatch;
  DispID:integer;
begin
  Disp:=DCOM.GetAppServer; 
  Disp.GetIDsOfNames('Func1',1,DispID);  //получаем числовой индефикатор имени "Func1"
  Disp.Invoke(DispID,....); //вызывает метод по индификатору.
end;


Это сообщение отредактировал(а) Caduser - 24.1.2007, 09:56
PM MAIL ICQ   Вверх
CatATonik
Дата 24.1.2007, 10:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 12.1.2007
Где: Москва

Репутация: 2
Всего: 8



Вот примерный набросок, также смотри функцию DispatchInvoke в модуле ComObj.

Код


var
  FuncName: WideString;
  DispId: TDispId;
  Params: TDISPPARAMS;
  ExcepInfo: TExcepInfo;
  Result: PVariant;
  Server: IDispatch;
begin
  Server := Connection.GetServer as IDispatch;
  Server.GetIDsOfNames(GUID_NULL, @FuncName, 1, GetThreadLocale, @DispId);

  Params.rgvarg := @Args;
  Params.rgdispidNamedArgs := nil;
  Params.cArgs := ArgCount;
  Params.cNamedArgs := 0;

  Server.Invoke(DispId, GUID_NULL, 0, DISPATCH_METHOD, Params, Result, @ExcepInfo, nil);
end;


PM MAIL   Вверх
Caduser
Дата 25.1.2007, 08:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 2.10.2006
Где: г. Хабаровск

Репутация: нет
Всего: 1



Спасибо CatATonik, чувствую ответ уже близко. Во всяком случае этот код:
Код

  Server := Connection.GetServer as IDispatch;
  FuncName := 'Func1';
  OleCheck(Server.GetIDsOfNames(GUID_NULL, @FuncName, 1, GetThreadLocale, @DispId));

DispId функции возвращает верно, но безнадёжно спотыкается на:
Код

  FillChar(Params, SizeOf(DispParams), 0);
  OleCheck(Server.Invoke(DispId, GUID_NULL, GetThreadLocale, DISPATCH_METHOD,
                  Params, Result, @ExcepInfo, nil));

с ошибкой "OLE error C0000005"  smile 
тестовая функция не имеет параметров, но подозреваю что дело в переменной Params: TDispParams, не понятно как её заполнять? 
Вообще есть библиотека типов сервера (_TLB.pas) может его как то прикурить сюда? например DispId можно оттуда взять, тогда не нужен будет метод GetIDsOfNames.


Это сообщение отредактировал(а) Caduser - 25.1.2007, 09:44
PM MAIL ICQ   Вверх
CatATonik
Дата 25.1.2007, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 12.1.2007
Где: Москва

Репутация: 2
Всего: 8



Так трудно сказать в чем дело. Может Result не установлен?
PM MAIL   Вверх
Caduser
Дата 26.1.2007, 05:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 2.10.2006
Где: г. Хабаровск

Репутация: нет
Всего: 1



Цитата(CatATonik @ 25.1.2007,  09:45)
Так трудно сказать в чем дело. Может Result не установлен?

Заработало! Подвела меня невнимательность  smile  просто Result должен быть OleVariant, а в Invoke нужно передавать указатель на Result:
Код

Invoke(DispId, GUID_NULL, GetThreadLocale, DISPATCH_METHOD,
            Params, @Result, @ExcepInfo, nil)

Спасибо, CatATonik!

P.S.
Единственный недостаток всего этого - неудобно формировать параметры для функций, уж больно их много у меня. Особенно обидно что все функции уже описаны в _TLB.pas , теперь задумался - а может раннее связывание можно организовать,  и быстрее будет работать, и проверка корректности вызовов сразу будет?

Это сообщение отредактировал(а) Caduser - 26.1.2007, 05:52
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: ActiveX/СОМ/CORBA"

Rrader
Girder

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами


  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Delphi
  • Вопросы по SQL и вопросы по базам данных, не связанные с Delphi, задавать здесь

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Rrader, Girder.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: ActiveX/СОМ/CORBA | Следующая тема »


 




[ Время генерации скрипта: 0.0561 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.