Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Oct : Multi-Threading

www.cryer.info
Managed Newsgroup Archive

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

Replies:

www.cryer.info
Managed Newsgroup Archive