Delphi 共享线程';公共财产

Delphi 共享线程';公共财产,delphi,thread-safety,Delphi,Thread Safety,我的类是从具有多个属性的TThread继承的,其中一个属性是TAdoDataSet。我的线程创建自己的TAdoConnection和TAdoDataSet。我的问题是: 1-在MyThread终止后,在主线程中使用数据集(MyThread.DataSet)是否安全?。 2-是否有更好的技术来实现此要求?我的意思是,创建一个打开数据集的线程,然后在主线程中使用数据集?回调函数还是PostMessage TmyProc =Procedure (Msg:TmyMsg) of object; Tm

我的类是从具有多个属性的TThread继承的,其中一个属性是TAdoDataSet。我的线程创建自己的TAdoConnection和TAdoDataSet。我的问题是: 1-在MyThread终止后,在主线程中使用数据集(MyThread.DataSet)是否安全?。 2-是否有更好的技术来实现此要求?我的意思是,创建一个打开数据集的线程,然后在主线程中使用数据集?回调函数还是PostMessage

TmyProc =Procedure (Msg:TmyMsg) of object;

  TmyThread = Class(TThread)
  private
    FConnection: TAdoConnection;
    FMyDataset :TAdoDataSet;
    FmyProc: TMyProc;
  protected
    procedure Execute; override;
    property myProc: TmyProc read FmyProc;
  public
    Constructor Create(myProc:TmyProc;
                      ConnectionString: WideString);
    property MyDataSet: TAdoDataSet read FMyDataset 
  end;

constructor TmyThread .Create(Susp:Boolean; myProc:TmyProc; 
   ConnectionString: WideString);
begin

// here I create the connection and mydataset;
// and my callback comes from main thread;
FmyProc := myProc; 

inherited Create(Susp);
end;


procedure TmyThread.Execute;
begin
  inherited;
  CoInitialize(nil);
  // here I open the connection and myDataset
  CoUninitialize();
end;


In the main thread :

procedure TForm1.Button1Click(Sender: TObject);
begin
  mt:=TmyThread.Create(True,ACallBack,ADOConnection1.ConnectionString);
  mt.FreeOnTerminate := True;
  mt.OnTerminate:= OnThredDone;
  mt.Resume;
end;

3-正如您在上面的代码中看到的,freeonterminate:=True,但是当我使用:if Assigned(MyThread)测试它时,MyThread保持活动状态

这不是线程安全的。在电话里

已分配(读取)

仅仅测试零。这和

零神话阅读

但是,在Delphi中,对对象调用Free不会将对象指针设置为nil


Delphi有一个内置的FreeAndNil过程,可以确保将对象指针设置为nil。人们应该使用它。

数据集可能只能从创建的线程访问。此外,使用FreeOnTerminate意味着您在启动线程后无法引用它,除非您在OnTerminated事件中非常小心。将连接和数据集移动到主线程中作为属性,并使用Synchronize(MyDataSet)通过MyTrea访问它们如何?如果所有代码都在主线程中运行,为什么还要麻烦线程呢?另外,你不能同步对象,你需要同步方法。它只运行主线程中的代码。ADO使用与创建它们的线程有亲缘关系的单元线程COM对象。除非使用
comarshalinterreadinterfaceinstream()
/
CoGetInterfaceAndReleaseStream()
IGlobalInterfaceTable
手动封送COM对象,否则无法跨线程边界使用ADO。
MyThread.Free;
if Assigned(MyThread) then  //this will return true
begin
  MyThrerad.MyDaSet.First; //and this will give you an access violation!
end;