Delphi 7,Windows 7,事件处理程序,重用代码 [英] Delphi 7, Windows 7, event handler, re-entrent code

查看:136
本文介绍了Delphi 7,Windows 7,事件处理程序,重用代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些非常旧的代码(15 + yr),用于运行正常,旧的软件版本较老的较慢的机器。它现在不行,因为如果失败的竞争条件。这是一个一般的问题:告诉我为什么我应该知道并期望这段代码的失败,以便我可以识别其他代码中的模式:

 程序TMainform.portset(iComNumber:word); 
begin
windows.outputdebugstring(pchar('portset'+ inttostr(icomnumber)));

with mainform.comport do
try
如果打开然后打开:= False; //关闭端口
comnumber:= iComNumber;
baud:= baudrate [baudbox.itemindex];
奇偶校验:= pNone;
databits:= 8;
stopbits:= 1;
open:= true;
flushinbuffer;
flushoutbuffer;
如果打开,那么mainform.statusb.Panels [5] .text:= st [1,langnum] {Port open}
else mainform.statusb.Panels [5] .text:= st [ langnum]; {port set OK}
除了
在E上:exception do begin
windows.OutputDebugString('port in'exception in)
mainform.statusb.Panels [5] .text:= st [3,langnum];
哔哔声
哔哔声
结束
结束
windows.outputdebugstring('portset exit');
结束

请注意,flushinbuffer受到EnterCriticalSection()的保护; AFAIK没有任何其他的保护,AFAIK没有消息处理部分。 BUT



当这个代码从一个点击事件调用时,它会部分地通过,然后被一个paint事件中断。 >

我所做的唯一跟踪是使用outputdebugstring。在出口第二个字符串显示之前,我可以看到第一个字符串重复输入。这是真的还是幻觉?



跟踪如下所示:

  4.2595 [4680]图表单击事件
4.2602 [4680]点击事件处理程序的portset 1'
4.2606 [4680]图形绘制事件
4.2608 [4680] portset 1'从油漆事件处理程序'
4.2609 [4680] portset exit

4.3373 [4680] portset exit

这是一个竞争条件:表单的 paint事件处理程序单击事件处理程序代码完成之前调用,这会导致失败。序列号是AsyncPro。没有线程代码。是的,有更多的代码,没有它在portset 1之前没有做任何事情,但它在它到达之前写入一个表单:

  with graphform do begin 
如果没有waitlab.Visible然后开始
waitlab.visible:= true;
waitprogress.position:= 0;
waitprogress.visible:= true;
waitprogress.max:= 214;
结束
结束
mainform.Statusb.panels [5] .text:= gcap [10,langnum];

不要阻止:做错了什么,我该找什么? p>

解决方案

标准绘画事件本身不会发生,只能通过消息检索触发。因此,您显示的代码的唯一方式可能会被中断,如果串行组件本身或分配给它的事件处理程序正在执行一些将呼叫线程的消息队列泵入新消息的事情。


I've got some very old code (15+yr) that used to run ok, on older slower machines with older software versions. It doesn't work so well now because if fails a race condition. This is a general question: tell me why I should have known and expected the failure in this code, so that I can recognise the pattern in other code:

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;

Note that flushinbuffer is protected with EnterCriticalSection(); AFAIK Nothing else is protected, and AFAIK there are no message handling sections. BUT

When this code is called from a click event, it gets part way through, then is interupted by a paint event.

The only tracing I have done is with outputdebugstring. I can see the first string repeated on entry before the second string is shown on exit. Is that real, or is it an illusion?

The trace looks like this:

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

This is a race condition: The paint event handler of the form is called before the click event handler code finishes, which causes failures. Serial code is AsyncPro. No thread code. Yes, there is more code, no it doesn't do anything in particular before "portset 1" but it does write to a form before it gets there:

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]; 

Don't hold back: What is it doing wrong, what should I be looking for?

解决方案

A standard paint event cannot happen on its own, it can only be triggered by message retrieval. So the only way the code you showed could be interrupted the way you describe is if either the Serial component itself, or an event handler you have assigned to it, is doing something that pumps the calling thread's message queue for new messages.

这篇关于Delphi 7,Windows 7,事件处理程序,重用代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆