Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.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 Delphi-从第二个线程更新全局字符串_Multithreading_Delphi_Delphi Xe - Fatal编程技术网

Multithreading Delphi-从第二个线程更新全局字符串

Multithreading Delphi-从第二个线程更新全局字符串,multithreading,delphi,delphi-xe,Multithreading,Delphi,Delphi Xe,我正在Delphi(XE)中试验多线程,遇到了在主VCL线程和第二个工作线程之间使用全局变量的问题 我的项目涉及第二个工作线程,它扫描一些文件,并用当前文件名更新globalvar字符串。然后通过主VCL线程上的计时器拾取此globalvar,并更新状态栏 但我注意到,它偶尔会出现“无效指针操作”或“内存不足”或工作线程停止响应(可能是死锁) 因此,我创建了一个测试应用程序来识别并大大增加出错的机会,这样我就可以看到发生了什么 type TSyncThread = class(TThread

我正在Delphi(XE)中试验多线程,遇到了在主VCL线程和第二个工作线程之间使用全局变量的问题

我的项目涉及第二个工作线程,它扫描一些文件,并用当前文件名更新globalvar字符串。然后通过主VCL线程上的计时器拾取此globalvar,并更新状态栏

但我注意到,它偶尔会出现“无效指针操作”或“内存不足”或工作线程停止响应(可能是死锁)

因此,我创建了一个测试应用程序来识别并大大增加出错的机会,这样我就可以看到发生了什么

type
  TSyncThread = class(TThread)
  protected
    procedure Execute; override;
end;

var
  Form11: TForm11;
  ProgressString : String;
  ProgressCount : Int64;
  SyncThread : TSyncThread;
  CritSect : TRTLCriticalSection;

implementation

{$R *.dfm}

procedure TForm11.StartButtonClick(Sender: TObject);
begin
  Timer1.Enabled := true;
  SyncThread := TSyncThread.Create(True);
  SyncThread.Start;
end;

procedure TForm11.StopbuttonClick(Sender: TObject);
begin
  Timer1.Enabled := false;
  SyncThread.Terminate;
end;

procedure TForm11.Timer1Timer(Sender: TObject);
begin
  StatusBar1.Panels[0].Text := 'Count: ' + IntToStr(ProgressCount);
  StatusBar1.Panels[1].Text := ProgressString;
end;

procedure TSyncThread.Execute;
var
  i : Int64;
begin
  i := 0;
  while not Terminated do begin
    inc(i);
    EnterCriticalSection(CritSect);
    ProgressString := IntToStr(i);
    ProgressCount := i;
    LeaveCriticalSection(CritSect);
  end;
end;

initialization
  InitializeCriticalSection(CritSect);
finalization
  DeleteCriticalSection(CritSect);
我将计时器间隔设置为10ms,以便它读取大量数据,同时工作线程正在全速运行以更新全局变量字符串。果不其然,在出现上述错误之前,这个应用程序在运行时只持续了一秒钟

我的问题是,VCL定时器中全局var的读取操作是否需要在关键部分运行?-如果是,原因是什么?。从我的理解来看,这只是一个读操作,而写操作已经在一个关键部分运行,我不明白为什么会出现问题。如果我把计时器中的读数也放在一个关键部分,它工作得很好……但是我不高兴这样做而不知道为什么


我是多线程新手,因此希望您能帮助我解释为什么这个简单的示例会导致各种问题,以及是否有更好的方法从工作线程访问字符串。

Delphi string是在堆上分配的,它不是某个地方的静态缓冲区。变量本身只是一个指针。当您的读取线程访问一个字符串时,同时这个字符串正被另一个线程释放,坏事情就会发生。您正在访问已释放的内存,可能再次分配给其他内容,等等

即使该字符串是一个静态缓冲区,更新操作也不是原子的,因此您可能正在使用此时正在更新的损坏字符串(一半是新数据,一半是旧数据)


因此,您需要使用与写入操作相同的关键部分来保护您的读取操作。

谢谢这是一个令人难以置信的快速回复,并详细解释了问题-正是我想要的。我总是想知道发生了什么,而不是盲目地做一些事情,因为它是有效的。你知道你可以去掉锁,只使用一个整数变量在线程之间共享数据吗?对于64位整数来说有点混乱,但是对于32位整数来说却微不足道。