![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Indy (idTCPServer) + синхронизация с VCL thread [D7, WinXP]
Аноним © (2004-07-07 14:08:00)У меня в программе в обработчике OnExecute должно идти обращение к компонентам формы => все это дело нужно синхронизовать с VCL потоком. Так?
Если, да то как?
Думаю, что нужно писать в AThread.Synchronize(...), НО вот что писать в качестве аргумента? Ну, в принципе, понятно, что процедуру, но где она должна быть обьявлена.
Спасибо.
Аноним (2004-07-07 19:54:00) [1]Digitman © (07.07.04 15:08) [1]
alienserg (07.07.04 19:16) [2]
Спасибо за помощь.
alienserg (2004-07-07 19:29:00) [2]если использовать TIdSync, надо не забыть добавить
uses IdSync;
alienserg (2004-07-07 19:16:00) [3]я в соседней ветке запостил примеры, приведу и здесь.
**** Использование TIdSync ****
type
TStartFileReceive = class(TIdSync)
protected
public
FSize: integer;
FSenderName: string;
procedure DoSynchronize; override;
constructor Create(AThread: TIdThread; aSize: integer; senderName:string);
class procedure Add(AThread: TIdThread; aSize: integer; senderName:string);
end;
implementation
{ TStartFileReceive }
class procedure TStartFileReceive.Add(AThread: TIdThread; aSize: integer; senderName:string);
begin
with TStartFileReceive.Create(AThread, aSize, senderName) do begin
try
Synchronize;
finally
Free;
end;
end;
end;
constructor TStartFileReceive.Create(AThread:TIdThread; aSize:integer; senderName:string);
begin
inherited Create(AThread);
FSize:=aSize;
FsenderName:=senderName;
end;
procedure TStartFileReceive.DoSynchronize;
var
fileForm: TfileReceiveForm;
msgForm: TamcForm;
begin
msgForm:=mainForm.getBuddyForm(FsenderName,false);
if msgForm<>nil then begin
fileForm:=msgForm.fileReceiveForm;
if fileForm<>nil then begin
fileForm.DrawBar(4,inttostr(FSize));
fileForm.receiveState:=sReceiving;
fileForm.DrawBar(1,'receiving...');
fileForm.btDir.Enabled:=false;
fileForm.ProgressBar1.Max:=FSize;
end;
end;
end;
чтобы все это дело сработало, я в OnExecute делаю
TStartFileReceive.Add(AThread, aFilesize, senderName);
**** Использование PostMessage ****
type
TFileParams = record
fileName: string;
fileSize: integer;
md5hash_server: string;
md5hash_local: string;
end;
PFileParams = ^TFileParams;
TsfSendForm = class(TForm)
...
private
...
procedure DoFileSendStart(recAddr: integer); message WM_SEND_START;
...
public
...
end;
const
WM_SEND_START = WM_USER + 1;
implementation
procedure TsfSendForm.DoFileSendStart(recAddr: integer);
var
fileParams: PFileParams;
fileItem: TListItem;
i: integer;
begin
fileParams:=PFileParams(recAddr);
lbFile.Caption:=fileParams.fileName;
fileItem:=TListItem.Create(lvFiles.Items);
for i:=0 to 3 do fileItem.SubItems.Add('');
fileItem.SubItems[0]:=inttostr(fileParams.fileSize);
fileItem.SubItems[1]:=fileParams.md5hash_local;
fileItem:=lvFiles.Items.AddItem(fileItem);
fileItem.Caption:=fileParams.fileName;
ProgressBar1.Max:=fileParams.fileSize;
ProgressBar1.Position:=0;
DrawBar(1,'sending...');
DrawBar(2,'0%');
DrawBar(3,inttostr(0));
DrawBar(4,inttostr(fileParams.fileSize));
Dispose(fileParams);
end;
вызов DoFileSendStart (для этого надо иметь под рукой хэндл окна, которому посылаешь сообщение):
var
fileParams: PFileParams;
...
New(fileParams);
fileParams.fileName:=Copy(FFileName,Length(FLocalDir)+2,999999);
fileParams.fileSize:=FFileSize;
fileParams.md5hash_local:=Fmd5hash;
PostMessage(TsfSendForm(FParentForm).Handle,WM_SEND_START,integer(fileParams),0);
Digitman (2004-07-07 15:08:00) [4]
> Думаю, что нужно писать в AThread.Synchronize(...),
не сможешь ты так писать, потому что Synchronize() - защищенный метод
здесь кто-то подсказывал намедни, что в составе Инди для этой цели есть якобы специальный компонент класса TIdSync, но ничего по этому поводу сказать не могу - в моей Инди-палитре его нет, возможно он есть в иных версиях Инди-пакета
чтобы не городить огород с использованием собственных наследников TIdPeerThread и TIdThreadManager, можно организовать в форме обработчик некоего своего предопределенного win-сообщения и посылать это сообщение из тела обработчика OnExecute() окну формы вызовом Send/PostMessage() .. по получению сообщения обработчик в форме делает с нужными VCL-контролами все что угодно