//线程类如下
type
   Tusercj = class(TThread)
      user: string;
      pass: string;
       name: string; //昵称
      date_str: string; //采集日期
      date_t: tDate; //采集日期
      Date_curr: TDate; //现在的日期  采集当前的日期
      get_day: Integer; //需要采集的天数
      htmlcode: string;
      str: string;
      error_count: Integer; //出现错误统计
      tab: TTabSheet;
      memo: TmxMemo; //日志框
      param: TStringList; //POST提交参数
      idssl: TIdSSLIOHandlerSocket; //SSL需要的
      idhttp: TIdHTTP; //POST获取数据控件
      vercode: TMemoryStream; //验证码文件字节
      qry, qry1, qry2: TADOQuery;
   protected
      procedure Execute; override; //线程启使
      procedure main(); //采集主函数
      procedure data_count(); //数据统计
      procedure save_xml(); //生成XML
      procedure log(str: string); //日志
      function get_data(): Integer; //获取指定日期数据
      function check_error(): Boolean; //检查是否达到最大错误
      function selectuser(): Boolean; //检查当天日期的数据是否存在
      function get_vercode(): string; //获取验证码
   end;Execute;下有进行TAB和M的Create
   tab := TTabSheet.Create(Form1.pgc1);
   tab.Caption := self.user;
   tab.Parent := Form1.pgc1;
   tab.PageControl := Form1.pgc1;
   tab.Align := alClient;
   memo := tmxmemo.Create(tab);
   memo.Parent := tab;
   memo.Align := alClient;问题是 创建的MEMO 不接收任何消息和事件,比如像上面这样写 MEMO正常显示 但在上面添加一句memo.lines.add('text'); MEMO在窗体上就显示不出来了,用sendmessage发送消息也接受不了,但如果创建后 手动点开窗体上的MEMO,再用sendmessage发送消息,又可以正常接收,问题就是 为什么MEMO会不正常显示

解决方案 »

  1.   

    这是一个线程安全问题。
    不应在线程里创建及访问界面元素。建议:在准备好数据后,通过SendeMessage消息给主窗体,告诉主窗体已处理完毕。这时主窗体可挂起该线程(看你的需要),构造界面元素并读取线程类准备好的数据.....
      

  2.   

    多谢版主大人,但我现在的问题是,memo是要现实线程执行的日志,可以看到上面有一个LOG过程,就是就sendmessage发送给创建的memo数据用的,处理完毕再构建肯定是不行的
      

  3.   

    log数据采集过程? 
    总之,你的界面创建及访问,一定不能在线程中。
    如果考虑log过程,那么就应在线程启动前,将界面提前准备好就行了。
    线程execute时,postmessage附带读取数据提交给主线程,主窗体处理此消息,添加相关数据到Memo中。
      

  4.   

    execute是初始化各种数据和控件
    main是采集的主过程
    log下面是一个sendmessage发送日志的消息 是发送给本线程类下的MEMO的我这样写是想好控制,如果先把MEMO创建好,线程都不知道要将日志发送到哪个MEMO上 又要用到循环去读取MEMO的数据才好确定发送到哪个MEMO上 这样效率是不是太慢了
      

  5.   

    首先,再说明一下不要在线程里做 界面设置;
    其次,“如果先把MEMO创建好,线程都不知道要将日志发送到哪个MEMO上”,你完全可以在发送消息时附带线程的标识,通过此标识确定Memo(界面的初始化与线程创建,可以在同一位置处理并关联起来)。问题其实不复杂,多思考思考。不要因为一点小问题,去走“弯路”,到时还得绕回来
      

  6.   

    delphi 线程存取ui控件, 要同步~~~~要同步~~
      

  7.   

    参考一下 TTimer 代码,
    收到消息后,更新 Memo。
      

  8.   

    这位同学说的对,线程要使用同步函数操作界面,好像是syncronize函数,你查查帮助吧
      

  9.   

    线程不要直接使用界面元素,Delphi的窗口,控件都应该在主线程访问.syncronize是可以的,因为它是发消息给主线程,在主线程里面执行的
      

  10.   

    重载线程的构造函数,在构造函数中将主界面中的memo当做参数传递给线程中,然后使用就没有问题。你在线程的执行函数中创建这些肯定是不行的!
      

  11.   

    在线程中定义一个Memo对象
    _Memo:TMemo;重载线程单元构造函数
    public 
        //重载构造函数(这里定 义多少参数都可以
        constructor Create(aMemo:TMemo);
       //重载析构函数
        Destructor Destroy; override;//线程构函数函数(所有需要初始化的部分都写到这里面)
    constructor TNetThread.Create(aMemo:TMemol);
    begin
      _Memo := aMemo;
      FreeOnTerminate:=true;                 //标志着线程执行完毕后,自动释放资源
      inherited Create(true);                //线程创建时不执行,指定运行后方才执行(如果是false则创建后立即执行)
    end;//线程析构函数(线程结束后释放资源)
    destructor TNetThread.Destroy;
    begin
      _Memo := nil;
      inherited;
    end;//线程执行函数
    procedure TNetThread.Execute;
    begin
        _memo.lines.add('执行成功了');
    end;
      

  12.   

    估计你的Execute里修改memo后还的加一句,application.processMessage把消息发到主线程去更新界面
      

  13.   

    不需要Application.processMessage,直接改就可以看到,我经常这样用。Application.processMessage是在同一主线程中需要刷新控件时使用(此时可能有一个耗的操作在执行).
      

  14.   

    直接 SendMessage 给 Memo!