我用多线程调用API, 在线程的Execute中使用了同步Synchronize,问题是在线程执行的时候程序像死机一样没有反应,界面上的任何东西都无法使用,去掉Execute中的同步又恢复正常(虽可使用但是有时无法正常下载),请问怎么解决?type
   ThttpdownThread = class(TThread)
     private
    { Private declarations }
   procedure httpdown;
   protected
    procedure Execute; override;
   end;procedure ThttpdownThread.Execute;
begin
  Synchronize(httpdown);
end;procedure thttpdownthread.httpdown;
begin
//下载代码,其中使用了VCL
end;

解决方案 »

  1.   

    线程中使用VCL可视控件,会导致这些控件无法正常显示器
      

  2.   

    我覺得應該如此:
    procedure ThttpdownThread.Execute;
    begin
     httpdown;
    end;procedure thttpdownthread.httpdown;
    begin
    //下载代码,其中使用了VCL
     .....
     Synchronize(refreshForm1Memo);
     .....
    end;
      

  3.   

    线程中修改vcl的属性是不安全的
    修改memo的文字也是不行的
      

  4.   

    在线程中使用本类的过程是不需要加synchronize的吧
    我的理解是访问其他的类的过程的函数的时候需要线程的同步才用这个函数的 不知道自己理解的对不对?
      

  5.   

    我使用Synchronize是因为有时使用wininet函数会无法连接服务器,不一定什么时候,也不一定连接哪个服务器,使用Synchronize以后可以连接任何网站,不过就是在连接的时候界面上的任何东西都不能使用,像死机一样,我只想解决这个问题。
      

  6.   

    或者现在有别的办法让执行wininet的时候不出现假死状态也可以。
      

  7.   

    这个方法只是把Synchronize(httpdown);里的HTTPDOWN方法放到主界面线程里去执行,所以根本就起不到多线程的作用;
      

  8.   

    那应该怎么做多线程?如果去掉Synchronize就会无法连接。
      

  9.   

    Synchronize同步的原理就是把里面的过程压进主线程来做,
    如果你把你个需要耗费很多CPU时间的东西用Synchronize
    同步了,那你的主线程就会因为忙着别的东西而没有时间更
    新界面了,换句话说你的程序就和单线程没什么区别了。
    procedure ThttpdownThread.Execute;
    begin
      Synchronize(httpdown);
    end;
    你一开始就把线程要做的东西都压进了主线程,你这样的程序
    和单线程程序是一样的。你应该在ThttpdownThread.Execute;
    里面多写点东西,只是必须更新界面的代码写在ThttpdownThread.Getout
    里面就行了。
    具体的,我不想多说,你就按照这个思路更改你的程序即可。
    应尽量减少Synchronize的使用。用多了你的程序就和单线程一样了。还有,记得给分。angle097113(深思不解) 
    outer2000(天外流星) 说的都是正确的。
      

  10.   

    我使用Synchronize是因为如果不这样 httpdown里面的程序就会有问题,根本无法连接服务器。
    如果不用, ThttpdownThread这个线程刚开始执行的时候就会造成假死,界面上的任何东西都没办法点,标题栏也会变成白色。我只想解决使用Synchronize 怎么能不假死,是不是我创建多线程的方法有问题?
      

  11.   

    其实这个问题我认为可以这么解决:
    1,用到VCL都在THREAD里CREATE后使用;当然要注意释放了,呵呵
    2,这样你就没必要用SYNCH方法了,如果一定要给MEMO什么的加东西,可以单独写
    一个SYNCH方法;我想不会影响的
      

  12.   

    窗体1的源代码
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, wininet, StdCtrls, inetutil, Menus;  type
         TFtpconnThread = class(TThread)
         private
        { Private declarations }
       procedure ftpconn;
       protected
        procedure Execute; override;
       end;type
      TForm1 = class(TForm)
        Edit1: TEdit;
        Button1: TButton;
        Edit2: TEdit;
        Edit3: TEdit;
        Memo1: TMemo;
        MainMenu1: TMainMenu;
        a: TMenuItem;
        a1: TMenuItem;
        b: TMenuItem;
        b1: TMenuItem;
        c: TMenuItem;
        c1: TMenuItem;
        asdasdasd1: TMenuItem;
        adsasdsda1: TMenuItem;
        sddsasd1: TMenuItem;
        asdsdasd1: TMenuItem;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        hi, fi : HINTERNET;
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure tftpconnthread.Execute;
    begin
    Synchronize(ftpconn);
    end;procedure tftpconnthread.ftpconn;
    begin
       form1.hi := InternetOpen('VCS FTP', INTERNET_OPEN_TYPE_DIRECT, nil, nil, 0);
       connCheck(LongBool(form1.hi));
       form1.fi := InternetConnect(form1.hi, PChar(form1.edit1.text),21,
           PChar(form1.Edit2.Text), PChar(form1.Edit3.Text), INTERNET_SERVICE_FTP, 0, 0);
       connCheck(LongBool(form1.fi));
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
    test1:tftpconnthread;
    begin
    test1:=tftpconnthread.Create(true);
    test1.Resume;
    end;end.连接检查代码
    unit INetUtil;interfaceuses SysUtils, Classes, Windows, WinINet;   procedure connCheck(b: LongBool);implementationuses Unit1,Forms, Controls;
    procedure connCheck(b: LongBool);
    var
       TmpErr2   : DWORD;
       Len2      : DWORD;
       Buf2      : array[0..max_path] of char;
    begin
       Len2 := sizeof(Buf2);
       InternetGetLastResponseInfo(TmpErr2, Buf2, Len2);
       Buf2[Len2] := #0;
       if buf2<>'' then
       form1.memo1.lines.Add(buf2);
    end;
    end.
    各位可以试试连接一个ftp服务器,点击连接(button1)后,窗体1上的Mainmenu就不能点了,一直到连接完毕。
      

  13.   

    把你检查的代码写到THREAD的一个方法;不单独一个UNIT;
    单独写一个METHOD;就是ADD一条到MEMO里;这个方法 SYN;procedure tftpconnthread.Execute;
    begin
    CHECK;
    ftpconn;
    //ADD MEMO ITEM;USE SYN。。
    end;
      

  14.   

    楼主,你把所有的任务都放进了Synchronize中了,这样和没有使用线程是一样的,只要把操作VCL的部分放到Synchronize中就可以了。
      

  15.   

    问题已经解决:因为我在formcreate写了一些vcl操作的代码,让api函数有时不能正常执行,不知道是因为我用的盗版还是delphi本身有问题,可悲。