关键部分不起作用

时间:2014-02-13 06:10:25

标签: multithreading delphi

我有这个主要表格

TForm1 = class(TForm)    
  fReceiver: TMessageReceiver;
  fCS: TCriticalSection;  
  constructor Create(aOwner: TComponent); override; **Create Critcal section**
  destructor Destroy(); override; **Delete critical section**
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  fcs.Acquire;
  //Perform Action
  fcs.Release;

end;

TMessageReceiver= class(TReceiver)
  private
    fFrame: TForm1;
  public
    constructor Create(aFrame: TForm1);
    destructor Destroy(); override;
    function HandleMessage(aUserName: string): boolean; override;
  end;

 function TMessageReceiver.HandleMessage(aUserName: string): boolean;
 begin
   fFrame.fcs.Acquire;
    //Do Lengthy OP
   fFrame.fcs.Release;
 end;

我有两个类,其中TMessageReceiver在一个线程中被调用。我尝试在这两个类之间进行同步。在调用句柄消息后,如果我尝试单击该按钮,它将进入临界区块,尽管它已在HandleMessage中获取。 我不知道这段代码有什么问题。

任何建议都会有很大的帮助。

2 个答案:

答案 0 :(得分:4)

Acquire成功召唤有两种可能的解释。

  1. 关键部分是无主的。
  2. 关键部分由调用线程拥有。
  3. 您可以使用关键部分结构的DebugInfo字段来检查递归计数:http://msdn.microsoft.com/en-gb/magazine/cc164040.aspx

    选项1(关键部分不归属)的一个可能原因是您创建了多个关键部分实例。

    选项2的可能原因是所有代码都在同一个线程中运行。

    我们无法为您提供更详细的诊断,因为您从问题中删除了所有必要的细节。这是一个典型的情况,SSCCE会帮助每个人。


    更广泛地看待你的代码,它显示出令人担忧的迹象。在TMessageReceiver.HandleMessage中,您获得了一个关键部分,并着手执行冗长的操作。但是在TForm1.Button1Click输入事件处理程序中,您尝试声明相同的关键部分。如果在漫长的操作过程中执行此操作,则将阻止UI线程。您将拥有一个无响应的用户界面,并且可能Windows会将您的窗口标记为无响应并将其重命名。

    在输入事件处理程序中看到一个关键部分是非常令人惊讶的。这具有成为主要设计缺陷的所有症状。

答案 1 :(得分:2)

关键部分确保没有其他线程同时进入受保护的代码段,它不能防止从同一线程重新进入。这意味着如果您在受保护的代码段中的任何地方碰巧调用Application.ProcessMessages,则可以轻松地获得重新入口问题。只是猜一下......