Форум: "Corba";
Текущий архив: 2006.03.12;
Скачать: [xml.tar.bz2];
Внизмногопоточность и 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 вся ветка
Форум: "Corba";
Текущий архив: 2006.03.12;
Скачать: [xml.tar.bz2];
Память: 0.46 MB
Время: 0.011 c