我有这个主要表格
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中获取。 我不知道这段代码有什么问题。
任何建议都会有很大的帮助。
答案 0 :(得分:4)
Acquire
成功召唤有两种可能的解释。
您可以使用关键部分结构的DebugInfo
字段来检查递归计数:http://msdn.microsoft.com/en-gb/magazine/cc164040.aspx
选项1(关键部分不归属)的一个可能原因是您创建了多个关键部分实例。
选项2的可能原因是所有代码都在同一个线程中运行。
我们无法为您提供更详细的诊断,因为您从问题中删除了所有必要的细节。这是一个典型的情况,SSCCE会帮助每个人。
更广泛地看待你的代码,它显示出令人担忧的迹象。在TMessageReceiver.HandleMessage
中,您获得了一个关键部分,并着手执行冗长的操作。但是在TForm1.Button1Click
输入事件处理程序中,您尝试声明相同的关键部分。如果在漫长的操作过程中执行此操作,则将阻止UI线程。您将拥有一个无响应的用户界面,并且可能Windows会将您的窗口标记为无响应并将其重命名。
在输入事件处理程序中看到一个关键部分是非常令人惊讶的。这具有成为主要设计缺陷的所有症状。
答案 1 :(得分:2)
关键部分确保没有其他线程同时进入受保护的代码段,它不能防止从同一线程重新进入。这意味着如果您在受保护的代码段中的任何地方碰巧调用Application.ProcessMessages
,则可以轻松地获得重新入口问题。只是猜一下......