【问题标题】:Delphi/Indy IdHttpServer not multithreaded?Delphi/Indy IdHttpServer 不是多线程的?
【发布时间】:2010-10-20 04:21:16
【问题描述】:

我使用的是 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 进行测试,使用 2 个浏览器。我有第一个连接到“本地主机”,我马上听到哔哔声。然后我切换到第二个浏览器,并让它连接到本地主机(在不到 10 秒的时间内),但它不会立即发出哔哔声。它等待第一个请求完成,然后发出哔哔声,再等待 10 秒。

我认为这些组件是多线程的?有没有我可以设置的属性让它按照我想象的方式运行(两个请求都会立即得到答复)。

【问题讨论】:

  • 您可以通过为 ContentText 值返回 Format('%d %d', [MainThreadID, GetCurrentThreadID]) 来检查所有内容是否在同一个线程上运行。如果真的是多线程的,那么你在每个请求中得到的两个值会互不相同,而且两个响应的第二个值可能也会不同。
  • 如果我可以让您对替代方案感兴趣:我已经开始 xxm.sourceforge.net 将我正在从事的项目开源,该项目可以解决这个问题和类似问题。我还没有在 Delphi 2006 上尝试过,它基于 Delphi 7,但运气好的话应该可以工作。

标签: multithreading delphi http indy


【解决方案1】:

GUI 在这 10 秒内响应,因此它是多线程的 长时间操作 把你的代码放到另一个线程中——你会得到你想要的

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;

【讨论】:

    【解决方案2】:

    不是 Indy,TIdHTTPServer 对此行为负责!这是网络浏览器!

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

    因此,Firefox 对同一个 URI 的 2 个请求进行序列化。同时打开2个不同的浏览器(例如IE和Firefox),同时请求http://localhost/,你会得到预期的结果。

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

    【讨论】:

    • 是的,就是这样!我使用了Firefox和Internet Explorer,得到了预期的结果,非常感谢!我的代码中有一个显示相同行为的错误,所以当我看到 Firefox 也这样做时,我认为我的代码是完美的......
    【解决方案3】:

    我使用过 Indy 10 idHTTPServer,它是多线程的。阻止您的应用程序的可能是“哔”或“睡眠”命令。因为虽然组件是多线程的,但是有些命令可能还是会锁住整个进程。

    【讨论】:

    • 出于某种原因,Indy 在为第二个请求触发 OnCommandGet 之前等待第一个请求完成。就像它已将 OnCommandGet 方法包装在关键部分中一样。它可能为每个请求使用不同的线程,但如果 Indy 仍然串行触发它们,那将毫无用处。 Beep 和 Sleep 函数不会阻塞某些 OTHER 线程。
    • 因为我已经开发了一个包含该组件的完整应用程序,所以我很确定它是多线程的。如果没有问题,请发布您的代码,让我们一起检查以找出问题;)
    • 谢谢,试试这个链接的代码,让我知道你看到了什么:benziegler.com/stuff/IndyTest.zip
    • 我疯了,但找不到解决方案。它似乎在单独的线程中接受和处理请求,但它等待另一个线程停止以实际开始做某事。可能是因为我们从本地机器发出了 2 个请求。
    • 感谢您的尝试。它非常令人沮丧,它应该是多线程的,但事实并非如此。从同一台机器发出 2 个请求应该不是问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 2012-07-29
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 2021-11-22
    相关资源
    最近更新 更多