如果主线程持有一个临界区,那么一个函数是否会尝试获取临界区块,如果它也在主线程上?

时间:2012-08-28 16:24:59

标签: multithreading delphi

我正在分析多线程应用程序中的一点点丢失。我想这个函数我试图理解主线程中的行为。为了确保我已在其中输入和退出关键部分代码。同样的关键部分也用于程序启动(进入关键部分)和终止(离开关键部分)。

如果我错了,请纠正我。如果我的函数在主线程中起作用,则应允许输入临界区。但事实并非如此 - 我的功能只是停止进入关键部分。根据我的理解,这个函数在另一个线程中起作用。

我的方法是否正确理解哪个函数在哪个线程中起作用?

3 个答案:

答案 0 :(得分:4)

只需使用调试器即可。在应用程序的启动代码中或应用程序的任何消息处理程序中设置断点,并在调试器线程窗口中检查当前线程ID。然后在相关函数中设置断点,并在执行到达该函数时检查线程ID。如果它们不匹配,则不会在运行UI消息的同一线程上调用该函数。

当您在调试器中停止使用函数时,您可以查看调用堆栈窗口以查看导致函数调用的调用序列。这可以提供一些洞察你如何到达那里,以及你如何在不同的线程上到达那里。

答案 1 :(得分:0)

我相信你是以错误的方式使用关键部分。 想象一下,你有一个可能在你的主线程和其他线程中修改的变量。每次要访问此变量时,首先Acquire关键部分;像这样:

if MyCriticalSection.TryEnter then  // MyVariable is accessible
begin
  MyVariable := MyVariable + 1;
  MyCriticalSection.Release;
end
else begin
  // do something useful and try again in a few milliseconds.
end;

请记住,当您致电Acquire时,调用线程将被冻结,直到关键部分可用。因此,如果您在应用程序开头调用Acquire,则第二次调用它将冻结您的主线程。

答案 2 :(得分:0)

您无法将其锁定在主线程内。始终在线程中使用临界区。将cs:TRTLCriticalSection声明为全局变量。调用任何线程。在不在主线程中的执行过程内锁定和解锁cs,或者在线程中的create构造函数中解锁。

你也无法读取主线程中的cnt变量。但是Synchronize方法更新mainCnt变量以在主线程

中读取它
var //global
  cs :TRTLCriticalSection;
  cnt:integer;  //use it only inside thread
  mainCnt:integer; //same value for cnt. use it inside a main thread.

///formcreate..
begin
  InitializeCriticalSection(cs);

///formdestroy
  DeleteCriticalSection(cs);

type
  TThrInc = class(TThread)
  private
    fAnyParam:Integer;
  protected
    procedure Execute; override;
  public
    constructor Create(anyparam:integer);
  end;


constructor TThrInc.Create(anyparam:integer);
begin
  fAnyParam:=AnyParam;  //you dont need this
end;

procedure TThrInc.execute;
var tmpcnt:integer;
begin
  EnterCriticalSection(cs);
  try begin
    inc(cnt);
    tmpcnt:=cnt;
  end except end;
  LeaveCriticalSection(cs);

  Synchronize(
    procedure
    begin
      mainCnt:=tmpcnt;
    end);
end;