2

我正在尝试使用线程进行 Web 服务调用。出于这个原因,我定义了一个简单的对象并从线程中调用它的方法。

但我意识到,在销毁该对象后,我仍然可以使用它的方法而不会出现任何错误,并且它会返回正确的答案。怎么可能?你有什么意见吗?

// TThreadMethod is defined in Classes.pas 

TThreadMethod = procedure of object;


*********************
      Interface 
*********************

TMyObject = class(TObject)
  procedure DoSomething;
end;

TMyThread = class(TThread)
private
  FMethod : TThreadMethod;
protected
  procedure Execute; override;
public
  constructor Create(aMethod: TThreadMethod);
end;

*********************
   Implementation 
*********************

// I called the thread and destroyed the object immediately. 

procedure TForm1.Button1Click(Sender: TObject);
var
  aObject : TMyObject;
begin
  aObject := TMyObject.Create;
  TMyThread.Create(aObject.DoSomething);
  FreeAndNil(aObject); // Object itself was destroyed here.
end;

constructor TMyThread.Create(aMethod: TThreadMethod);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  FMethod := aMethod;
  Resume;
end;

procedure TMyThread.Execute;
begin
  Sleep(10000); // wait 10 sec. before calling the method
  // The object was already destroyed but it doesn't produce any error!
  FMethod; // It calls the web service method and returns correct result. But how???     
end;

procedure TMyObject.DoSomething;
begin
  // Call a web service method and show the result on the form.
end;
4

1 回答 1

7

该方法不绑定到对象,而是绑定到类...

type
TMyObject = class(TObject)
 published
  procedure DoSomething;
end;
TSomeProcedure=Procedure of object;

  TForm1 = class(TForm)
  .....
  end;

var
  Form1: TForm1;

implementation    
{$R *.dfm}    
procedure TForm1.Button2Click(Sender: TObject);
var
 p:TSomeProcedure;
 M:TMethod;
begin
 m.Code := TMyObject.MethodAddress('DoSomething');
 m.Data := nil;
 p := TSomeProcedure(m);
 p;
end;

procedure TMyObject.DoSomething;
begin
  Showmessage('Hallo');
end;

编辑一个额外的例子是

type
TMyObject = class(TObject)
 published
  procedure DoSomething;
end;
procedure TMyObject.DoSomething;
begin
  Showmessage('Hallo');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 o1,o2:TMyObject;
begin
 o1:=TMyObject.Create;
 o2:=TMyObject.Create;
 Memo1.Lines.Add(IntToHex(Integer(TMyObject.MethodAddress('DoSomething')),4));
 Memo1.Lines.Add(IntToHex(Integer(o1.MethodAddress('DoSomething')),4));
 Memo1.Lines.Add(IntToHex(Integer(o2.MethodAddress('DoSomething')),4));
 o1.Free;
 o2.Free;
end;
于 2013-05-30T21:49:26.907 回答