我有一些非常旧的代码(15 年以上),过去运行良好,在较旧的较慢机器上运行较旧的软件版本。它现在不能很好地工作,因为如果失败了竞争条件。这是一个普遍的问题:告诉我为什么我应该知道并预料到这段代码中的失败,以便我可以识别其他代码中的模式:
procedure TMainform.portset(iComNumber:word);
begin
windows.outputdebugstring(pchar('portset ' + inttostr(icomnumber)));
with mainform.comport do
try
if open then open := False; // close port
comnumber:=iComNumber;
baud:=baudrate[baudbox.itemindex];
parity:=pNone;
databits:=8;
stopbits:=1;
open:=true;
flushinbuffer;
flushoutbuffer;
if open then mainform.statusb.Panels[5].text:=st[1,langnum] {Port open}
else mainform.statusb.Panels[5].text:=st[2,langnum]; {port set OK}
except
on E: exception do begin
windows.OutputDebugString('exception in portset');
mainform.statusb.Panels[5].text:=st[3,langnum];
beep;
beep;
end;
end;
windows.outputdebugstring('portset exit');
end;
请注意,flushinbuffer 受 EnterCriticalSection() 保护;AFAIK 没有其他东西受到保护,AFAIK 没有消息处理部分。但
当从单击事件调用此代码时,它会中途完成,然后被绘制事件中断。
我所做的唯一跟踪是使用 outputdebugstring。在退出时显示第二个字符串之前,我可以看到第一个字符串在输入时重复。这是真的,还是幻觉?
跟踪如下所示:
4.2595 [4680] graph form click event
4.2602 [4680] portset 1 'from click event handler'
4.2606 [4680] graph form paint event
4.2608 [4680] portset 1 'from paint event handler'
4.2609 [4680] portset exit
4.3373 [4680] portset exit
这是一个竞争条件:在单击事件处理程序代码完成之前调用表单的绘制事件处理程序,这会导致失败。序列号是 AsyncPro。没有线程代码。是的,还有更多代码,不,它在“portset 1”之前没有做任何特别的事情,但它确实在到达那里之前写入了一个表单:
with graphform do begin
if not waitlab.Visible then begin
waitlab.visible:=true;
waitprogress.position:=0;
waitprogress.visible:=true;
waitprogress.max:=214;
end;
end;
mainform.Statusb.panels[5].text:=gcap[10,langnum];
不要退缩:它做错了什么,我应该寻找什么?