访问线程中的vcl组件!德尔福

时间:2010-11-23 13:46:37

标签: multithreading delphi

所以,我的目标是在另一个线程中启动一个函数。此外,我需要从新线程访问其他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';

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

提前致谢。

3 个答案:

答案 0 :(得分:9)

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

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

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

答案 1 :(得分:5)

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

答案 2 :(得分:0)

如果你使用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;