Delphi/Indy的IdHttpServer不支持多线程吗?

10

我使用Delphi 2006和Indy 10。我创建了一个窗体并放置了一个IdHttpServer组件。我为该窗体创建了一个OnCreate事件以使服务器处于活动状态,并在服务器的OnCommandGet中输入以下行:

procedure TForm3.IdHTTPServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
   Beep;
   Sleep(10000);
   AResponseInfo.ContentText := DateTimeToStr(Now);
end;

请注意等待10秒钟。
然后我使用两个浏览器在Firefox中进行测试。 我让第一个浏览器连接到“localhost”,然后立即听到嘟声。 然后我切换到第二个浏览器,并让它在不到10秒的时间内连接到localhost,但它不会立即响铃。 它等待第一个请求完成,然后响铃,并等待另外10秒。
我认为这些组件是多线程的? 是否有一些属性可以设置使其按照我想象的方式运行(两个请求都会立即得到回答)。

1
你可以通过返回Format('%d %d',[MainThreadID,GetCurrentThreadID])作为ContentText值来检查是否一切在同一线程上运行。如果确实是多线程的,每个请求中获得的两个值将彼此不同,并且两个响应的第二个值也可能不同。 - Rob Kennedy
如果您对另一种选择感兴趣的话:我已经开始开源一个项目,它可以解决这个问题和类似的问题。该项目网址为http://xxm.sourceforge.net/。虽然我还没有在Delphi 2006上尝试过,但它是基于Delphi 7的,带着一点运气应该可以工作。 - Stijn Sanders
3个回答

13

这与Indy和TIdHTTPServer无关,而是浏览器造成的!

Firefox在同一服务器上为不同请求共享TCP连接。

因此,Firefox对于相同URI的2个请求进行序列化处理。同时打开2个不同的浏览器(例如IE和Firefox),在两者中都请求http://localhost/,您将得到预期的结果。

至于您的问题的答案:是的,每个TIdHTTPServer.OnCommandGet事件都在自己的“调度程序”线程中执行,并且可以同时执行。


2
是的,就是这样!我使用了Firefox和Internet Explorer,并得到了预期的结果,非常感谢!我的代码中有一个错误,显示了相同的行为,所以当我看到Firefox也这样做时,我认为我的代码是完美的... - Ben Ziegler

1

在这10秒钟内,GUI是响应的,因此它是多线程的,对于长时间的操作,将您的代码放入另一个线程中 - 您将获得想要的结果。

unit uSomeThread;

interface

uses
  System.Classes;

type
  TSomeThread = class(TThread)
  protected
    procedure Execute; override;
  end;

implementation


procedure TSomeThread.Execute;
begin
  //  Beep;
  Sleep(10000);
end;

end.

...........

    procedure TServer.IdHTTPServerCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  cContext: TClientContext;
  t: TSomeThread;
begin
//  Beep;
//  Sleep(10000);

  t := TSomeThread.Create(true);
  t.FreeOnTerminate := true;
  t.Start;

  AResponseInfo.ResponseNo := 200;
  AResponseInfo.CacheControl := 'no-cache';
  AResponseInfo.CustomHeaders.Add('Access-Control-Allow-Origin: *');
  AResponseInfo.ContentText := 'ok';
  AResponseInfo.ResponseNo := 200;
  AResponseInfo.WriteContent;
  Beep;

end;

1

我使用了Indy 10 idHTTPServer,它是多线程的。阻塞您的应用程序可能是“beep”或“sleep”命令。因为尽管组件是多线程的,但某些命令仍然可能锁定整个进程。


由于某种原因,Indy 在触发第二个请求的 OnCommandGet 之前会等待第一个请求完成。就像它在一个关键段中包装了 OnCommandGet 方法一样。它可能为每个请求使用不同的线程,但如果 Indy 仍然按顺序触发它们,那就没有用了。Beep 和 Sleep 函数不会阻塞其他线程。 - Ben Ziegler
既然我已经使用这个组件开发了一个完整的应用程序,我非常确定它是多线程的。如果没有问题的话,请发布你的代码,让我们一起检查并找出问题 ;) - BYK
1
谢谢,请尝试从此链接中获取代码,让我知道你看到了什么: http://www.benziegler.com/stuff/IndyTest.zip - Ben Ziegler
我疯了,但是找不到解决方案。它似乎接受并处理单独的线程请求,但它等待其他线程停止才真正开始执行某些操作。可能是因为我们正在从本地机器发出2个请求。 - BYK
1
谢谢您的尝试。这非常令人沮丧,它应该是多线程的,但实际上并不是。从同一台机器进行两个请求不应该成为问题。 - Ben Ziegler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接