Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Oct : Multi-Threading
| Subject: | Multi-Threading |
| Posted by: | "David Fealkoff" (fealko..@iatinc.net) |
| Date: | Mon, 16 Oct 2006 01:06:47 |
I am attempting to implement multithreading in an application but am stuck.
Below I have the elements of my code.
1) I've created 2 objects which I attempt to use to create a threaded HTTP
connection with sync'd updates to the main app.
TSyncClass = class
protected
FWorkCount: integer;
FWorkCountMax: integer;
FStringStream: TStringStream;
procedure BeginDownload;
procedure UpdateDownload;
procedure EndDownload;
public
procedure DoSynchronize(AThread: TIDThread; AMethod: TThreadMethod);
end;
TDownloadThread = class(TidThread)
protected
procedure httpworkbegin(ASender: TObject; AWorkMode: TWorkMode;
AWorkCountMax: Integer);
procedure httpwork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount:
Integer);
procedure httpworkend(ASender: TObject; AWorkMode: TWorkMode);
public
frequestURL: string;
fhost: string;
fport: integer;
fstream: TStringStream;
procedure Run; override;
end;
2) The TSyncClass procedures follow
{TSyncClass}
procedure TSyncClass.BeginDownload;
begin
frmDownload.pbarDownload.Min := 0;
frmDownload.pbarDownload.Max := FWorkCountMax;
end;
procedure TSyncClass.UpdateDownload;
begin
frmDownload.pbarDownload.Position := FWorkCount;
end;
procedure TSyncClass.EndDownload;
begin
frmSoundStage.StrStream.CopyFrom(FStringStream,FStringStream.Size);
end;
procedure TSyncClass.DoSynchronize(AThread: TIdThread; AMethod:
TThreadMethod);
begin
AThread.Synchronize(AMethod);
end;
3) The TDownloadThread procedures follow
{TDownloadThread}
procedure TDownloadThread.Run;
begin
with TIdHTTP.Create(nil) do
begin
try
//populate request header
Request.URL := frequestURL;
OnWork := httpwork;
OnWorkBegin := httpworkbegin;
OnWorkEnd := httpworkend;
Connect(fhost,fPort);
while connected do
Get(Request.URL, fstream);
finally
Free;
end;
end;//with
Stop;
end;
procedure TDownloadThread.httpworkbegin(ASender: TObject; AWorkMode:
TWorkMode; AWorkCountMax: Integer);
var
C: TSyncClass;
begin
C := TSyncClass.Create;
try
with C do
begin
FWorkCountMax := AWorkCountMax;
DoSynchronize(self,BeginDownload);
end;
finally
C.Free;
end;//try
end;
procedure TDownloadThread.httpwork(ASender: TObject; AWorkMode: TWorkMode;
AWorkCount: Integer);
var
C: TSyncClass;
begin
C := TSyncClass.Create;
try
with C do
begin
FWorkCount := AWorkCount;
DoSynchronize(self,UpdateDownload);
end;
finally
C.Free;
end;//try
end;
procedure TDownloadThread.httpworkend(ASender: TObject; AWorkMode:
TWorkMode);
var
C: TSyncClass;
begin
C := TSyncClass.Create;
try
with C do
begin
FStringStream.CopyFrom(TDownloadThread(ASender).fstream,TDownloadThread(ASender).fstream.Size);
DoSynchronize(self, EndDownload);
end;
finally
C.Free;
end;//try
end;
4) Main form code
downloadThread := TDownloadThread.Create;
try
with downloadThread frmMain do
begin
FreeOnTerminate := True;
frequestURL := 'http://' + frmSystemTest.edtServerHost.text + ':'
+
frmSystemTest.edtServerPort.text + '/GetQueue?clid=' +
InttoStr(TProductionInfo(lbProductions.Items.Objects[lbProductions.ItemIndex]).selectedclipid);
fhost := frmSystemTest.edtServerHost.Text;
fport := StrToInt(frmSystemTest.edtServerPort.Text);
Start;
finally
downloadThread.Free;
end;
5) It all seemed pretty straightforward under the assumption that in my
main form (shown above) when I call "Start" that the "Run" procedure
happens. By the way, I got the
structure for this implementation off of the Internet so I don't know how
valid it is. The assumptions I made were that the "Run" procedure would
run, the idHTTP events would subsequently trigger and
I could use those events to (a) pass download status information (b) capture
the download stream to the main form after the "WorkEnd" event. Clearly my
application fails at (b) and having not tried a multithreaded application
before I couldn't detect that the threading actually occured. That is
setting breakpoints didn't seem to work. So, if anyone could give me a
pointer about where I'm going wrong or some little detail I'm missing or
even a better way of doing this I'd appreciate it.
David