本文介绍了Delphi 7偶尔死锁改变来自IdHTTPListener事件的TLabel.Font.Style的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想知道有没有人可以帮助一个非常棘手的零星(不可重复)的问题 - 可能与线程有关。我在Delphi 7(它是旧代码...),运行IdHttpListener(Indy)。下面的代码是从一个庞大的繁琐的应用程序复制而来,但希望足以解释。传入的HTTP请求运行以下事件 - 其中web_lock是我在顶部定义的TCriticalSection。我在一个关键部分做,因为Web请求导致我需要是原子的变化。

 过程TFWebServer.WebServerCommandGet(Thread :TIdPeerThread; 
RequestInfo:TIdHTTPRequestInfo; ResponseInfo:TIdHTTPResponseInfo);

var S,PageString:string;

begin
web_lock.Acquire;
PageString:='';
if(copy(RequestInfo.Document,1,15)='/ _ Request_Part_')然后开始
s:= copy(RequestInfo.Document,16,length(RequestInfo.Document));
FMainGui.doFunction(s);
PageString:='OK';
结束//在这里还有更多的其他案例...
ResponseInfo.ContentType:='text / plain';
ResponseInfo.ResponseNo:= 200;
ResponseInfo.ContentStream:= TMemoryStream.Create;
ResponseInfo.ContentStream.Write(PageString [1],length(PageString)*
sizeof(PageString [1]));
ResponseInfo.ContentLength:= length(PageString)* sizeof(PageString [1]);
web_lock.Release;
结束

然后,我的FMainGui.doFunction会这样做: -

  procedure doFunction(s:String); 
var i,j:integer;
begin
i:= strtoint(s);
for j:= 1 to pages do begin //页面是动态的 - 但正确设置
如果(j = i)// // Pagelabs [j]始终是可见的TLabel
Pagelabs [ j] .Font.Style:= [fsBold]
else Pagelabs [j] .Font.Style:= [];
结束
结束

位简化 - Pagelabs是一组我在页面上显示的动态创建的TLabels,一个您已选择使用Web请求获得粗体。



问题:偶尔和不可预知的是,我遇到了一些处理Web请求的死锁 - 它只是冻结了圆形的旋转鼠标指针,并且没有恢复。如果我在Delphi中调试它,调用堆栈是空的,我只能通过汇编代码 - 害怕我不能工作,这意味着什么!通过在每一行代码之间写入一行文本文件,我将其跟踪到Pagelab [j] .Font.Style:= [fsBold]行...所以当错误是零星的时候,当它发生时,它总是这条线被锁定了。



我感谢这是一个大型应用程序的片段,但是有什么明显的我做错了吗?例如 - 是否可以安全地从HTTP侦听器触发的线程更改GUI属性?或者有什么不同我应该在做什么?



任何想法非常感谢,
谢谢,
Wes

解决方案

您不能从工作线程处理UI控件,只能从主GUI线程!



您有两个选项:



您可以通过 TThread.Synchronize()过程阻止您的HTTP线程和临时切换到主线程。就像在这个例子中一样:





您可能更喜欢延迟不同步执行通过




  • Windows消息(使用PostMessage并避免SendMessage)


  • AsyncCall库


  • 线程队列方法使用像OmniThreadsLibrary的东西




第一个选项可能会减慢你的速度,因为GUI线程中的任何长时间的处理也会释放您的HTTP处理程序。



第二个选项将需要制作任何所需数据的快照副本,并将其与延迟的呼叫请求一起传递(因为VCL更新代码可能在HTTP处理程序(或多个HTTP处理程序)之后(或之后)的任何随机时间执行。几个HTTP处理程序会要求GUI更新是正常的,您必须检查哪些HTTP处理程序会传递最近的数据,并跳过其他请求。例如

Wondered if anyone could help with a really tricky sporadic (not consistently reproducible) issue - possibly to do with threads. I'm in Delphi 7 (it's old code...), running an IdHttpListener (Indy). Code below is copied from a large cumbersome app - but hopefully enough to explain. An incoming HTTP request runs the following event - where web_lock is a TCriticalSection I define at the top. I do it in a critical section as the web requests causes changes that I need to be atomic.

procedure TFWebServer.WebServerCommandGet(Thread: TIdPeerThread;
  RequestInfo: TIdHTTPRequestInfo; ResponseInfo: TIdHTTPResponseInfo);

var S,PageString : string;

begin
  web_lock.Acquire;
  PageString:=' ';
  if (copy(RequestInfo.Document,1,15)='/_Request_Part_') then begin
    s:=copy(RequestInfo.Document,16,length(RequestInfo.Document));
    FMainGui.doFunction(s);
    PageString:='OK';
  end; // Lots more else cases here...
  ResponseInfo.ContentType:='text/plain';
  ResponseInfo.ResponseNo:=200;
  ResponseInfo.ContentStream:=TMemoryStream.Create;
  ResponseInfo.ContentStream.Write(PageString[1],length(PageString)*
    sizeof(PageString[1]));
  ResponseInfo.ContentLength:=length(PageString)*sizeof(PageString[1]);
  web_lock.Release;
end;

and then, my FMainGui.doFunction(s) does something like this:-

procedure doFunction(s : String);
var i,j : integer;
begin
  i:=strtoint(s); 
  for j:=1 to Pages do begin // Pages is dynamic - but correctly set
    if (j=i) then // Pagelabs[j] is always a visible TLabel
      Pagelabs[j].Font.Style:=[fsBold]
      else Pagelabs[j].Font.Style:=[];
  end;
end;

Bit simplified - Pagelabs is a set of dynamically created TLabels that I display on a page, and the one you've selected using the web request gets made bold.

THE PROBLEM: Occasionally, and unpredictably, I get some kind of deadlock dealing with the web request - it just freezes, with circular swirly mouse pointer, and doesn't recover. If I'm debugging it in Delphi, the call stack is empty, and I can only step through the assembly code - afraid I'm not up to working what that means! I tracked it down to the Pagelabs[j].Font.Style:=[fsBold] line above, by writing one line text files between every single line of code... so while the error was sporadic, when it did occur, it was always that line it locked up on.

I appreciate this is a snippet of a large app, but is there anything obvious I'm doing wrong? Eg - should it be safe to change GUI properties from a thread triggered by the HTTP Listener? Or is there something different I should be doing?

Any ideas much appreciated,Thanks,Wes

解决方案

You cannot manipulate UI controls from worker threads, only from the main GUI thread!

You have two options:

You may block your HTTP threads and temporary switch to main thread by TThread.Synchronize() procedure. Like in this example:

http://docwiki.embarcadero.com/CodeExamples/Seattle/en/Synchronize_(Delphi)

You may prefer delayed out-of-sync execution via

First option might slow you down, for any long processing in the GUI thread would also freeze your HTTP handlers.

Second options would require making a "snapshot" copy of any required data and passing it along with the deferred call request ( as the VCL update code might be executed at any random time AFTER (or during) the HTTP handler (or several HTTP handlers). It would be normal when several HTTP handlers would request GUI updates and you would have to check which of them passed the most recent data and skip other requests for example.

这篇关于Delphi 7偶尔死锁改变来自IdHTTPListener事件的TLabel.Font.Style的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-02 06:55