delphi - 在长轮询请求中断开IdHTTP

时间:2015-06-01 12:45:15

标签: multithreading delphi delphi-7 idhttp

我正在我的deplhi项目中实现实时聊天,该项目通过向服务器发出GET请求来接收新消息。如果没有新消息发生,服务器本身会在20秒后关闭连接。上面描述的代码位于一个单独的线程中(它是在访问聊天“页面”时创建的),因此它不会冻结GUI。当我从聊天中转到非聊天页面时,我在thread_chat之外调用此代码以使线程退出:

if thread_chat <> nil then
begin
  thread_chat.Terminate;
  thread_chat := nil;
end;

然而,由于我的服务器超时是20秒,因此线程只有在收到响应时才会关闭(是的,这听起来很合理,因为我的线程循环是while not Terminated do)。所以我要找的是在请求中间关闭HTTP连接。

Attemp#1

最初我通过调用它来查看TerminateThread

TerminateThread(thread_chat.Handle, 0)

这个工作正常,直到我试图第二次杀死线程 - 我的应用程序完全冻结。所以我去了

Attemp#2

我创建了一个全局变量URL_HTTP: TIdHTTP,我收到了具有此功能的服务器页面内容:

function get_URL_Content(const Url: string): string;
var URL_stream: TStringStream;
begin
  URL_HTTP := TIdHTTP.Create(nil);
  URL_stream := TStringStream.Create(Result);
  URL_HTTP.Get(Url, URL_stream);
  if URL_HTTP <> nil then
  try
    URL_stream.Position := 0;
    Result := URL_stream.ReadString(URL_stream.Size);
  finally
    FreeAndNil(URL_HTTP);
    FreeAndNil(URL_stream);
  end;
end;

当我在thread_chat

之外调用此代码时
if thread_chat <> nil then
begin
  URL_HTTP.Disconnect;
  thread_chat.Terminate;
end;

我得到EidClosedSocket异常(在撰写此帖后进行了一些测试后,我得到了EAccessViolation错误。)

我没有想法。如何在服务器响应之前关闭HTTP请求?

procedure thread_chat.Execute;  //overrided
begin
    while not Terminated do
      if check_messages then  //sends request to the server, processes response, true if new message(s) exist
        show_messages;
end;

1 个答案:

答案 0 :(得分:1)

尝试这样的事情:

type
  TThreadChat = class(TThread)
  private
    HTTP: TIdHTTP;
    function CheckMessages: Boolean;
    procedure ShowMessages;
  protected
    procedure Execute; override;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Stop;
  end;

constructor TThreadChat.Create;
begin
  inherited Create(False);
  HTTP := TIdHTTP.Create(nil);
end;

destructor TThreadChat.Destroy;
begin
  HTTP.Free;
  inherited;
end;

function TThreadChat.CheckMessages: Boolean;
var
  Resp: string;
begin
  //...
  Resp := HTTP.Get(Url);
  //...
end;

procedure TThreadChat.ShowMessages;
begin
  //...
end;

procedure TThreadChat.Execute;
begin
  while not Terminated do
  begin
    if CheckMessages then
       ShowMessages;
  end;
end;

procedure TThreadChat.Stop;
begin
  Terminate;
  try
    HTTP.Disconnect;
  except
  end;
end;

thread_chat := TThreadChat.Create;

...

if thread_chat <> nil then
begin
  thread_chat.Stop;
  thread_chat.WaitFor;
  FreeAndNil(thread_chat);
end;