我正在我的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连接。
最初我通过调用它来查看TerminateThread
TerminateThread(thread_chat.Handle, 0)
这个工作正常,直到我试图第二次杀死线程 - 我的应用程序完全冻结。所以我去了
我创建了一个全局变量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;
答案 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;