进度显示那个没有问题。但是因为界面会被堵塞,stop按钮就按不了,现在在想办法。tftp和进度条都放到线程里面去还是不能。
所以请高手看看呀。
下载用的indy的tftp组件。
下面是主界面的代码 就2个按钮unit Unit6;interfaceuses
  SysUtils, Classes, Controls, Forms,
  StdCtrls, ComCtrls, 
  Unit7;type
  TForm7 = class(TForm)
    txt1: TEdit;
    btn1: TButton;
    btn2: TButton;
    lbl1: TLabel;
    pb1: TProgressBar;
    procedure btn1Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
  private    { Private declarations }
  public
    down:TTftpDown;
    { Public declarations }
  end;var
  Form7: TForm7;implementation{$R *.dfm}procedure TForm7.btn1Click(Sender: TObject);
begin
  if not Boolean(down) then
    down:=TTftpDown.create(True,'192.168.0.28','1.pdf','c:\1.pdf',nil,StrToInt(txt1.Text));
  down.Execute;
end;procedure TForm7.btn2Click(Sender: TObject);
begin
  if Boolean(down) then
    down.Terminate;
end;end.下面是线程代码:unit Unit7;interface
uses
  Classes,Dialogs ,Controls,ComCtrls ,Forms
  ,IdBaseComponent, IdComponent, IdUDPBase, IdTrivialFTP,SysUtils;type
  TTftpDown = class(TThread)
  private
    { Private declarations }
    FHost:string;
    FReFile:string;
    FLoFile:string;
    aCount:Integer;
    aCountMaxt:Integer;
    FTftp:TIdTrivialFTP;
    aDisplayFrm:TForm;
    pb1:TProgressbar;
    procedure myOnWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
    procedure myOnWork(ASender: TObject; AWorkMode: TWorkMode;
      AWorkCount: Integer);
    procedure myOnWorkBegin(ASender: TObject; AWorkMode: TWorkMode;
      AWorkCountMax: Integer);
    procedure myOnTerminate(sender:TObject);
    procedure displayProgress;
    procedure clearPb;
  protected  public
    wordDone:Boolean;
    constructor create(bSuspend:Boolean;sHost,sReFile,sLoFile:string;aPb:TProgressBar;aMax:Integer);
    procedure Execute; override;
    procedure stop;
  end;implementation
uses
 Unit6;{ TTftpDown }procedure TTftpDown.clearPb;
begin
//  form7.pb1.Min:=0;
  Form7.pb1.Position:=0;
end;constructor TTftpDown.create(bSuspend: Boolean; sHost, sReFile,
  sLoFile: string;aPb:TProgressBar;aMax:Integer);
begin
  inherited create(bsuspend);
  FTftp:=TIdTrivialFTP.Create(nil);
  FreeOnTerminate:=True;
  FTftp.BufferSize:=512; //自定义包的大小,这里设置小一点儿 为了看进度。
  FTftp.OnWork:=myOnWork;
  FTftp.OnWorkBegin:=myOnWorkBegin;
  FTftp.OnWorkEnd:=myOnWorkEnd;
  FTftp.Host:=sHost;
  FReFile:=sReFile;
  FLoFile:=sLoFile;
  aDisplayFrm:=TForm.Create(nil);
  pb1:=TProgressBar.Create(aDisplayFrm);
  pb1.Parent:=aDisplayFrm;
  aDisplayFrm.Width:=500;
  pb1.Left:=10;
  pb1.Top:=20;
  pb1.Width:=aDisplayFrm.Width-20;
  pb1.Max:=aMax;
  pb1.Visible:=True;
  aDisplayFrm.Show;
  aCountMaxt:=aMax;
  Self.OnTerminate:=myOnTerminate;
end;procedure TTftpDown.displayProgress;
begin
  Form7.pb1.Position:=aCount;
end;procedure TTftpDown.Execute;
begin
  FTftp.Get(FReFile,FLoFile);
end;procedure TTftpDown.myOnTerminate(sender: TObject);
begin
  if Boolean(FTftp) then
    FTftp.Free;
  if Boolean(aDisplayFrm) then
    FreeAndNil(aDisplayFrm);
end;procedure TTftpDown.myOnWork(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCount: Integer);
begin
  if terminated then
  begin
    showmessage('取消下载');
    FTftp.Active:=False;
    Exit;
  end;
//  pb1.Position:=AWorkCount;
  pb1.Position:=AWorkCount;
end;procedure TTftpDown.myOnWorkBegin(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCountMax: Integer);
begin
  ShowMessage(IntToStr(AWorkCountMax)+':等于0说明indy-Tftp控件在这里也不能获得下载文件的大小');
//  self.Synchronize(clearPb);
  pb1.Position:=0;end;procedure TTftpDown.myOnWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
//  ShowMessage('work done halt here!');
end;procedure TTftpDown.stop;
begin
  Terminate;
end;end.

解决方案 »

  1.   

    TThreadr中的Terminate方法并不能真正地"终止"线程,而只是做了一个可终止标记,因为Delphi认为,直接强型终止线程是不安全的,可不导致某些资源不能被有效释放,所以推荐的做法应该是,调用了Terminate方法过后,在你的线程过程(一般是一个循环/阻塞)中检查Terminated的值是否为True,并自行做好一切"收尾"工作再安全退出整个过程.但是楼主这些的线程过程是直接调用了TFtp的Get这个方法(阻塞的),那你也可以用Win32API来实现强行终止(TerminateThread).
      

  2.   

    但是我在tftp的OnWork事件里面也不停的检查这个terminated是否为false的。
    线程不是很明白。
      

  3.   

    抱歉,看得不仔细,没看到你的onMyWork,那你现在的问题是:还是不能停止?或是其它?
      

  4.   

    线程中操作界面控件时,应该通过Synchronize来调用,我看到你代码里有一句//  self.Synchronize(clearPb);却被注释了,为何...
      

  5.   

    因为用了也没有用,因为clearPb这个事件其实也是在主线程里面执行的,所以在执行这个事件的时候Synchronize(displayProgress);
    每接收到一个包就会让主线程执行displayProgress这个事件,但是接收包是很短的间隔,所以我的stop按钮事件还是不行呀。根本就按不了。
    有人说idantifreeze,可是拖上去了,貌似没有作用而且还会提示错误,不过再一次运行就能stop按钮了。郁闷。
      

  6.   

    哦,onMyWork里加一句Application.ProcessMessages试试.
      

  7.   

    Application.ProcessMessages
    是滴。
    应该这样。
    不过indy这个 我停止用的tftp.disconnect;tftp.active:=false;
    结果:timeOut;
    现在问题的正常停止indy控件的顺序或者方法。
    jpexe的帮助很大呀。
    谢谢了
      

  8.   

    TProgressBar是vcl控件,要用它,得用Synchronize。仔细看看Delphi线程类与进程主线程同步的资料吧