【发布时间】:2018-04-23 20:01:18
【问题描述】:
我编写了一个multithread 应用程序来发送和接收 TCP 包。我遇到的问题是,当我调用下面代码的两次事件confirmBoxRecognized(peerIP: string) 时。我收到以下异常:
无法在正在运行或挂起的线程上调用 Start
如果我签入线程对象,我有 terminated == true 和 suspended == false。为什么我编码错误?
按照代码:
TThreadReadTCP = class(TThread)
private
context: TfrmBoxTest;
looping: Boolean;
procedure readTCP;
protected
procedure DoTerminate; override;
procedure Execute; override;
public
peerIP: String;
responseObject: TProtocolObject;
constructor Create(CreateSuspended: Boolean; ctx: TFrmBoxTest); overload;
end;
{ TThreadReadTCP }
constructor TThreadReadTCP.Create(CreateSuspended: Boolean; ctx: TFrmBoxTest);
begin
inherited Create(CreateSuspended);
Self.context := ctx;
FreeOnTerminate := True;
end;
procedure TThreadReadTCP.DoTerminate;
begin
looping := false;
inherited DoTerminate();
end;
procedure TThreadReadTCP.Execute;
begin
inherited;
looping := true;
readTCP;
end;
procedure TThreadReadTCP.readTCP;
var
buffer: TBytes;
begin
while looping do
begin
if context.tcpClientBox.Connected then
begin
try
buffer := TEncoding.ASCII.GetBytes(context.tcpClientBox.Socket.ReadLn());
//do something else
except on E:Exception do
ShowMessage('Error receiving TCP buffer with message: ' + e.Message);
end;
end;
end;
end;
procedure TfrmBoxTest.confirmBoxRecognized(peerIP: string);
begin
if (connectBoxTCP(peerIP)) then
begin
if Assigned(threadReadTCP) then
begin
threadReadTCP.Terminate();
threadReadTCP.Start(); // I get the exception here when I run this code twice...
end;
showBoxRecognized();
end;
sendBoxRecognized();
end;
我可以获得运行线程状态吗?或者任何人都可以解释我如何改进这段代码来解决这个问题?
非常感谢!
【问题讨论】:
-
所以线程是
terminated=true但是还没写完? -
就这样。
-
terminated只是一个布尔值,如果您希望线程终止,您可以设置。您可以在 while 循环中检查terminated来结束它,而不是检查looping。 -
AFAIK,我不记得有可能重新启动终止的线程。甚至从未尝试过。终止意味着终止。如果要重新启动它,请不要终止它。将它保持在一个循环中,该循环检查一些标志是否应该继续。如果没有,那么就继续循环和检查。要么,要么只是开始一个新的线程副本。事实上,如果您使用
FreeOnTerminate,那么从您调用Start的那一刻起,您确实不 想要保留对该线程的引用。从那一刻起,它必须被忽略。声明一个局部变量,而不是在表单中。 -
另外,好的线程设计是将其与所有 UI 控件隔离开来。这最好通过在它自己的单元中编写线程来完成,它甚至不使用任何 VCL 单元。它应该是独立的,并且不知道它是如何被使用的。 UI 更新应该以某种方式同步。我个人更喜欢触发同步事件。在任何情况下,线程都不能直接访问主 UI 线程中的任何 UI 控件,因为它们不是线程安全的。
标签: multithreading delphi delphi-xe3