【问题标题】:Access to vcl component in thread! Delphi在线程中访问 vcl 组件!德尔福
【发布时间】:2011-05-14 11:39:35
【问题描述】:

所以,我的目标是在另一个线程中启动一个函数。我还需要从新线程访问其他 vcl 组件。到目前为止,这是我的代码:

procedure TForm1.StartButtonClick(Sender: TObject);
var
thread1: integer;
id1: longword;
begin
   thread1 := beginthread(nil,0,Addr(Tform1.fetchingdata),nil,0,id1);
    closehandle(thread1);
end;

procedure TForm1.FetchingData;
var
  ...
begin
  Idhttp1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;   //<- error
  idhttp1.Request.ContentType := 'application/x-www-form-urlencoded';

我的程序挂起并且出现错误:模块 my.exe 中的异常 EAccessViolation 在 00154E53。模块“my.exe”中地址 00554E53 的访问冲突。读取地址 00000398。

提前致谢。

【问题讨论】:

    标签: multithreading delphi


    【解决方案1】:

    AV 的原因是您将 TForm 方法的地址传递给需要 TThreadFunc 的函数(请参阅 documentation of System.BeginThread())。像这样使用Addr() 是防止编译器指出您的错误的好方法。

    您需要做的是编写一个具有正确签名的包装函数,将表单实例作为参数传递,然后从该函数调用表单上的方法。

    但不要去那里,要么将代码编写为 TThread 的后代,要么(最好)使用更高级别的包装器,如 AsyncCallsOmni Thread Library。并确保您不在主线程中访问 VCL 组件,在工作线程中创建和释放您需要的组件。

    【讨论】:

      【解决方案2】:

      VCL(Gui 组件)只能从主线程访问。其他线程需要主线程才能访问VCL。

      【讨论】:

      • 而实现这一点的简单方法是发布 WM_USER 消息的辅助线程和响应它们的主线程。但是,在您的情况下,您可以通过使用 indy TidAntiFreeze 对象来实现相同的效果。阅读此http://stackoverflow.com/questions/37185/whats-the-idiomatic-way-to-do-async-socket-programming-in-delphi
      【解决方案3】:

      如果您使用的是 Delphi 或 Lazarus,您可以使用常规 TThread 尝试相同的操作。

          type
                TSeparateThread = class(TThread)
                  private
                  protected
                  public
                    constructor Create(IfSuspend: Boolean);
                    proceedure Execute; override;
                  // variables to fill go here
                  // s : String;
                  // i : Integer;
                  // etc...
                end;
      
              constructor TSeparateThread.Create(IfSuspend: Boolean);
              begin
                inherited Create(IfSuspend);    
              end;
      
              procedure TSeparateThread.Execute;
              begin
      
        // This is where you will do things with those variables and then pass them back.
      
              YourMainUnitOrForm.PublicVariableOf := s[i];
      
        // passes position 0 of s to PublicVariableOf in your Main Thread
      
              end;
      

      调用新线程如下:

      with TSeparateThread.Create(true) do
        begin
      
        // This is where you fill those variables passed to the new Thread
                s := 'from main program';
                i := 0;
        // etc...
      
          Resume; 
      
        //Will Start the Execution of the New Thread with the variables filled.
      
        end;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-02-08
        • 2014-07-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多