Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.03.12;
Скачать: CL | DM;

Вниз

многопоточность и COM   Найти похожие ветки 

 
vlad_ri   (2005-04-28 18:23) [0]

Наставьте на путь истинный :)

В приложении из дополнительного потока надо выполнить функцию на Application Server-e. В качестве Application Server-а выступает объект унаследованный от TMtsDataModule, подключение через TSocketConnection, интерфейс AppServer-а получаю следующим способом:
iSrvr := ITTestCOMThreadDisp(IDispatch(SocketConnection1.AppServer));

В интерфесе AppServer-а релизована и вызываеться всеголишь один метод.
При вызове из основного потока приложения всё выполняеться без ошибок, при выполнении из дополнительного метод выполняеться но при завершении выдаются исключения  EVariantInvalidArgError with message "Invalid argument" и ESocketConnectionError with message "Error reading from socket"

Вот реализация вызываемого метода:

procedure TTTestCOMThread.Test(const AString: WideString;
 Itterations: Integer; out Finished: WordBool);
var i: integer;
   tf: TextFile;
begin
 Finished := False;
 AssignFile(tf,"f:\test.txt");
 ReWrite(tf);
 i := 1;
 while i <= Itterations do
 begin
   writeln(tf,i,#9,AString);
   inc(i);
 end;
 CloseFile(tf);
 Finished := true;
end;


и реализация клиента


program Project1;

uses
 Forms,
 ComObj,
 ActiveX,
 Unit1 in "Unit1.pas" {Form1},
 TestComThread_TLB in "..\Server\TestComThread_TLB.pas";

{$R *.res}

begin
 CoInitFlags := COINIT_MULTITHREADED;
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.Run;
end.

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, TestComThread_TLB, DB, DBClient, MConnect, SConnect, StdCtrls;

type
 TForm1 = class(TForm)
   SocketConnection1: TSocketConnection;
   Button1: TButton;
   Edit1: TEdit;
   procedure FormCreate(Sender: TObject);
   procedure Button1Click(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
 private
   { Private declarations }
   iSrvr: ITTestCOMThreadDisp;
 public
   { Public declarations }
 end;

 TMyThread = class(TThread)
 protected
   procedure Execute; override;
 public
   iSrvr: ITTestCOMThreadDisp;
   IterCount: integer;
   procedure GetIterCount;
   constructor Create(Intrfc: ITTestCOMThreadDisp);
   destructor Destroy; override;
 end;

var
 Form1: TForm1;

implementation

uses ComObj, ActiveX;

{$R *.dfm}

constructor TMyThread.Create(Intrfc: ITTestCOMThreadDisp);
begin
 FreeOnTerminate := true;
 iSrvr := Intrfc;
 inherited Create(false);
end;

procedure TMyThread.GetIterCount;
begin
 IterCount := StrToInt(Form1.Edit1.Text);
end;

procedure TMyThread.Execute;
var stopped: WordBool;
begin
 Synchronize(GetIterCount);
 CoInitializeEx(nil, COINIT_MULTITHREADED);

 iSrvr.Test("Salut!!!",IterCount,stopped);

 CoUninitialize;
end;

destructor TMyThread.Destroy;
begin
 iSrvr := nil;
 inherited;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 SocketConnection1.Open;
 if SocketConnection1.Connected then
   iSrvr := ITTestCOMThreadDisp(IDispatch(SocketConnection1.AppServer));
end;

procedure TForm1.Button1Click(Sender: TObject);
var stopped: WordBool;
   tt: TTime;
   mt: TMyThread;
begin
//  tt := Now;
//  iSrvr.Test("Salut!!!",StrToInt(Edit1.Text),stopped);
//  if stopped then
//    ShowMessage(TimeToStr(Now-tt));
 mt := TMyThread.Create(iSrvr);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 iSrvr := nil;
 SocketConnection1.Close;
end;

end.


P.S.: Ногами не бить :)


 
Набережных С. ©   (2005-04-29 14:37) [1]

Тут дело не в СОМ, а в особенностях реализации TSocketConnection, не дружит он с многопоточностью на клиенте. Обмен с сервером он ведет в дополнительном потоке, а тот при приеме ответа от сервера переправляет его сообщением окну, созданному SocketConnection. А так как это окно создается в основном потоке, то и ответ придет туда, а не в тот поток, который вызвал метод. Если правильно помню, должна помочь установка SupportCallbacks в false. Но я бы не советовал, все равно там с потокобезопасностью не все ладно, насколько помню. Еще можно отказаться от MTA и маршалировать интерфейс в апартамент дополнительного потока, но смысл в этом нулевой - все равно вызов метода будет маршалирован в основной поток и в нем будет ждать ответа - окажутся заблокированы и главный, и дополнительный потоки, пока сервер не обработает метод. В общем, резюме такое: при работе через SocketConnection многопоточность использовать не стоит.


 
vlad_ri   (2005-04-29 16:12) [2]

Да действительно, вы оказались совершенно правы...

Замена на TDCOMConnection решила проблему.

Но раз уж вы упоминали о Callback, у меня появился встречный вопрос - как реализовывается Callback через TDCOMConnection?


 
Набережных С. ©   (2005-05-03 14:12) [3]


> vlad_ri   (29.04.05 16:12) [2]

При работе через DCOM работа идет через стандартные механизмы COM, дополнительно ничего не требуется.



Страницы: 1 вся ветка

Текущий архив: 2006.03.12;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.064 c
3-1137503688
Бульбаш
2006-01-17 16:14
2006.03.12
Ограничение макс. значения поля.


2-1140600957
iles
2006-02-22 12:35
2006.03.12
Не присваиваеться значение Элементу массива объектов Tedit


2-1141044901
Piero
2006-02-27 15:55
2006.03.12
TMemo


2-1140445949
Василь Быков
2006-02-20 17:32
2006.03.12
обновление в таблице ?


3-1137783314
olevacho_
2006-01-20 21:55
2006.03.12
Ошибка cannot transliterate character between character sets