if Assigned(FOnMessage) then FOnMessage(Sender,IDevice); 如果你的FOnMessage是执行主线程代码,那么 就造成死锁了。
To SydPink(Miss Syd.Barrett) FOnMessage中没有执行主线程代码,FOnMessage主要是更新界面,显示一些信息,并把信息保存到SqLServer数据库
to:SydPink(Miss Syd.Barrett) if Assigned(FOnMessage) then FOnMessage(Sender,IDevice); 如果你的FOnMessage是执行主线程代码,那么 就造成死锁了。这里为什么会死锁?我看到参考书中的例子也是不在临街区里运行主线程代码,但没有明确说临街区不能运行主线程代码,我的程序里在临街区直接对ui操作并没有出现异常。
To Scarlette(Lord of Borland) 请问你程序中多个线程中如果都需要更新界面或写数据库,使用什么方法实现同步的呢?我程序中发现的问题不止题目一个, 就是多个子线程共同访问临界区也有问题,经常有一个线程等待另一个线程退出临界区的情况,有时就死锁了。 现在只好用Mutex,在waitsingleobject的参数中指定超时,否则也是死锁。 我跟踪了程序,没有发现某个线程长时间占用FOnMessage过程执行的时间,每个FOnMessage执行的时间都不到一秒。
EnterCriticalSection(FCS);
try
FMsgType:=AMsgType;
FMsgStr:=AMsgStr;
if Assigned(FOnMessage) then
FOnMessage(Sender,IDevice);
finally
//解除阻塞
LeaveCriticalSection(FCS);
end;
http://community.csdn.net/Expert/topic/4342/4342487.xml?temp=.4390222
在MsgNotify.Free时MsgNotify.Free,MsgNotify不是线程对象
initialization
MsgNotify:=TMsgNotify.Create;
finalization
MsgNotify.Free;
会出现EnterCriticalSection()之后
没有LeaveCriticalSection()的情况吗
MsgNotify对象是全局对象,只有一个实例,
其他线程使用它的DoMessage方法来更新界面,
所以使用了临界区对象 TMsgNotify = class(TObject)
private
FCS: TRTLCriticalSection;
FMsgStr: string;
FMsgType: TMsgType;
FOnMessage: TDeviceMsgNotifiyEvent;
public
constructor Create;
destructor Destroy; override;
procedure DoMessage(Sender: TObject;const IDevice:IMsgNotityDevice;
AMsgType:TMsgType;AMsgStr:string);
property MsgStr: string read FMsgStr;
property MsgType: TMsgType read FMsgType;
property OnMessage: TDeviceMsgNotifiyEvent read FOnMessage write FOnMessage;
end;
{
********************************** TMsgNotify **********************************
}
constructor TMsgNotify.Create;
begin
inherited; //初始化阻塞对象
InitializeCriticalSection(FCS);
end;destructor TMsgNotify.Destroy;
begin
//删除阻塞对象
DeleteCriticalSection(FCS);
inherited;
end;procedure TMsgNotify.DoMessage(Sender: TObject;const IDevice:IMsgNotityDevice;
AMsgType:TMsgType;AMsgStr:string);
begin
//开始阻塞
EnterCriticalSection(FCS);
try
FMsgType:=AMsgType;
FMsgStr:=AMsgStr;
if Assigned(FOnMessage) then
FOnMessage(Sender,IDevice);
finally
//解除阻塞
LeaveCriticalSection(FCS);
end;
end;initialization
MsgNotify:=TMsgNotify.Create;
finalization
MsgNotify.Free;
EnterCriticalSection(FCS);
try
FMsgType:=AMsgType;
FMsgStr:=AMsgStr;
LeaveCriticalSection(FCS); // 应该这里也加上吧
if Assigned(FOnMessage) then
FOnMessage(Sender,IDevice);
finally
//解除阻塞
LeaveCriticalSection(FCS);
end;
EnterCriticalSection(FCS);
FMsgType:=AMsgType; // 对2个变量进行赋值应该不会引起什么异常吧
FMsgStr:=AMsgStr; // 不需要try..finally块
LeaveCriticalSection(FCS);
try
if Assigned(FOnMessage) then
FOnMessage(Sender,IDevice);
finally
// 如果这里也不需要,就把try..finally拿掉吧
end;
//开始阻塞
EnterCriticalSection(FCS);
try
FMsgType:=AMsgType;
FMsgStr:=AMsgStr;
if Assigned(FOnMessage) then
FOnMessage(Sender,IDevice); //事件处理代码中必须用到前面两个变量
finally
//解除阻塞
LeaveCriticalSection(FCS);
end;
2.FOnMessage里有对UI的操作,但没有使用Synchronize
EnterCriticalSection(FCS);
FMsgType:=AMsgType; // 对2个变量进行赋值应该不会引起什么异常吧
FMsgStr:=AMsgStr; // 不需要try..finally块
FMsgType2 := FMsgType;
FMsgStr2 := FMsgStr;
LeaveCriticalSection(FCS);
try
if Assigned(FOnMessage) then
FOnMessage(Sender,IDevice);
finally
// 如果这里也不需要,就把try..finally拿掉吧
end;.
.procedure OnMessage(Sender, IDevice: Integer); // 假设FOnMessage所指向的函数在这里
begin
//OnMessage里面使用的是FMsgType2、FMsgStr2,而外面使用的是FMsgType、FMsgStr,不冲突
end;
你的修改部分等于没有修改。
事件处理中引用的变量别的线程还是会修改
用个timer来定时检查,一般在主线程交互,我觉得用信号量更好,
但有个原则,一般,主线程(UI) 不能等待的
FOnMessage(Sender,IDevice);
如果你的FOnMessage是执行主线程代码,那么
就造成死锁了。
FOnMessage中没有执行主线程代码,FOnMessage主要是更新界面,显示一些信息,并把信息保存到SqLServer数据库
if Assigned(FOnMessage) then
FOnMessage(Sender,IDevice);
如果你的FOnMessage是执行主线程代码,那么
就造成死锁了。这里为什么会死锁?我看到参考书中的例子也是不在临街区里运行主线程代码,但没有明确说临街区不能运行主线程代码,我的程序里在临街区直接对ui操作并没有出现异常。
请问你程序中多个线程中如果都需要更新界面或写数据库,使用什么方法实现同步的呢?我程序中发现的问题不止题目一个,
就是多个子线程共同访问临界区也有问题,经常有一个线程等待另一个线程退出临界区的情况,有时就死锁了。
现在只好用Mutex,在waitsingleobject的参数中指定超时,否则也是死锁。
我跟踪了程序,没有发现某个线程长时间占用FOnMessage过程执行的时间,每个FOnMessage执行的时间都不到一秒。
子程序更新界面并没有使用主线程,仍然是在自己的线程中执行,与主线程是否挂起没有关系。