Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading tcriticalsection.create上的访问冲突_Multithreading_Delphi - Fatal编程技术网

Multithreading tcriticalsection.create上的访问冲突

Multithreading tcriticalsection.create上的访问冲突,multithreading,delphi,Multithreading,Delphi,我正在编写一个多线程聊天服务器应用程序。因此,临界截面是非常必要的。我刚刚为线程树视图创建了一个包装器类。它在客户机中工作得很好,但服务器会引发AV 有两种形式,FormServer(除了gui绘制之外,几乎不进行任何处理)和DataModuleServer(完成所有繁重工作) 首先创建FormServer 实际上,线程树视图位于另一个包装类TRoomTree中 TDataModuleServer.Create procedure TDataModuleServer.cr(Sender: TOb

我正在编写一个多线程聊天服务器应用程序。因此,临界截面是非常必要的。我刚刚为线程树视图创建了一个包装器类。它在客户机中工作得很好,但服务器会引发AV

有两种形式,FormServer(除了gui绘制之外,几乎不进行任何处理)和DataModuleServer(完成所有繁重工作)

首先创建FormServer

实际上,线程树视图位于另一个包装类TRoomTree中

TDataModuleServer.Create

procedure TDataModuleServer.cr(Sender: TObject);
begin
  Rooms := TRoomTree.Create (FormServer.tvRooms);
constructor TRoomTree.Create (TV : TTreeView);
begin

  if Assigned (TV) then
    fTreeView.Create (TV)
  else
    exit;
constructor TThreadTreeView.Create (TreeView : TTreeView = nil);
begin

  fLock := TCriticalSection.Create;

  if Assigned (TreeView) then
    fTreeView := TreeView
  else
    fTreeView := TTreeView.Create (nil);

end;
电视室:视觉树景

部队树。创建

procedure TDataModuleServer.cr(Sender: TObject);
begin
  Rooms := TRoomTree.Create (FormServer.tvRooms);
constructor TRoomTree.Create (TV : TTreeView);
begin

  if Assigned (TV) then
    fTreeView.Create (TV)
  else
    exit;
constructor TThreadTreeView.Create (TreeView : TTreeView = nil);
begin

  fLock := TCriticalSection.Create;

  if Assigned (TreeView) then
    fTreeView := TreeView
  else
    fTreeView := TTreeView.Create (nil);

end;
fTreeView:线程树视图

TThreadTreeView.Create

procedure TDataModuleServer.cr(Sender: TObject);
begin
  Rooms := TRoomTree.Create (FormServer.tvRooms);
constructor TRoomTree.Create (TV : TTreeView);
begin

  if Assigned (TV) then
    fTreeView.Create (TV)
  else
    exit;
constructor TThreadTreeView.Create (TreeView : TTreeView = nil);
begin

  fLock := TCriticalSection.Create;

  if Assigned (TreeView) then
    fTreeView := TreeView
  else
    fTreeView := TTreeView.Create (nil);

end;
fTreeView:普通树视图

现在TCriticalSection.Create在ntdll.dll中引发了一个AV异常

调用堆栈

:76cac41f KERNELBASE.RaiseException + 0x58
:0040469c NotifyNonDelphiException + $1C
:77ecb42b ; ntdll.dll
uThreadTreeView.TThreadTreeView.Create($26B4300) 
uRoomTree.TRoomTree.Create($26B4300)
uServer.TDataModuleServer.cr($26A48B0)
Classes.TDataModule.DoCreate
Classes.TDataModule.AfterConstruction
System.@AfterConstruction($26A48B0)
Classes.TDataModule.Create(???)
Forms.TApplication.CreateForm(???,(no value))
PlayburnServer.PlayburnServer
:773833aa kernel32.BaseThreadInitThunk + 0x12
:77ea9ef2 ntdll.RtlInitializeExceptionChain + 0x63
:77ea9ec5 ntdll.RtlInitializeExceptionChain + 0x36

任何帮助都将不胜感激。

部队树中。创建这行代码

fTreeView.Create(TV);
对您的访问违规负责。这是因为在尝试调用方法之前,
fTreeView
尚未初始化

Delphi实例的创建方式如下:

fTreeView := TThreadTreeView.Create(TV);

我不确定您的线程模型,但我相信您知道VCL控件只能从GUI线程访问。

VCL组件不应由工作线程访问。最好将其留给主VCL线程,并在VCL主线程和工作线程之间使用同步或消息。这件事之前已经讨论过了。从构造函数中退出是有问题的-您还跳过了哪些初始化?我认为在那里断言(Assigned(TV))
会更好,我宁愿让它有访问冲突或引发异常,也不愿停止而不是继续使用半构造的对象。。。你不会吗?呵呵,老的“UN”是最好的事实上,在XE3中,编译器已被更改为“终于”删除该功能!只花了20年@马丁尼还记得第一次启动Delphi 1时犯了同样的错误。快乐的日子!我想我第一次要求警告的时候是在D3。我现在仍然犯同样的错误,但是即时的AV和大量的Delphi经验现在让我很烦恼。很多时候我犯了这个错误,通常只需要几秒钟就意识到错误,但是我花了几个小时才发现代码有什么问题。@Arioch Delphi没有复制构造函数。那是C++。此功能是旧式TP对象的遗留问题。它没有任何价值,因为没有它,就有完全可以接受的替代品,可以达到同样的效果。很高兴它被杀了。这将意味着所有这些堆栈溢出问题的结束。这个特性的主要成就是混淆了落入陷阱的开发人员。