HwT*_*rap 0 delphi delphi-2010
我正在使用Threads(再次),这总是很痛苦......我的线程类中有一个函数,它是私有的.该函数返回一个布尔结果,以检查某个POP3服务器是否有效.检查工作,我测试了,看起来像至少工作,但我在Thread.Execute程序中尝试访问结果时遇到问题.我将解释更多,让我们去代码..这是宣言:
type
MyThread = class(TThread)
public
constructor Create(HostLine: string);
protected
procedure Execute; override;
procedure MainControl(Sender: TObject);
private
Host: string;
function CheckPOPHost: boolean; //this is the problematic function
end;
Run Code Online (Sandbox Code Playgroud)
所以函数是这样的:
function MyThread.CheckPOPHost: boolean;
var
MySocket: TClientSocket;
SockStream: TWinSocketStream;
Buffer: array[0..1023] of Char;
ReceivedText: string;
begin
Result:= false;
FillChar(Buffer, SizeOf(Buffer), #0);
MySocket:= TClientSocket.Create(Nil);
MySocket.Port:= 110;
MySocket.ClientType:= ctBlocking;
MySocket.Host:= Host;
MySocket.Active:= true;
if (MySocket.Socket.Connected = true) then
begin
SockStream := TWinSocketStream.Create(MySocket.Socket, 1000);
SockStream.WaitForData(10000);
while (SockStream.Read(Buffer, SizeOf(Buffer)) <> 0) do
ReceivedText:= ReceivedText + Buffer;
if Length(ReceivedText) > 0 then
ReceivedText:= PAnsiChar(ReceivedText);
if AnsiStartsStr('+', ReceivedText) then
Result:= true;
end;
SockStream.Free;
MySocket.Free;
end;
Run Code Online (Sandbox Code Playgroud)
所以,如果不想,你不需要阅读.但我正在连接到一些远程主机,并接收它的文本,如果收到的文本以"+"符号开头(默认为POP3服务器),我返回true ...但是当我尝试在Thread.Execute中执行此操作时:
if CheckPOPHost = true then
begin
Form1.Memo1.Lines.Append('Valid HOST:: '+Host);
Run Code Online (Sandbox Code Playgroud)
只是不工作.我认为很好记住,如果在函数内部,而不是做:
if AnsiStartsStr('+', ReceivedText) then
Result:= true;
Run Code Online (Sandbox Code Playgroud)
我做:
if AnsiStartsStr('+', ReceivedText) then
Form1.Memo1.Lines.Append('Valid HOST:: '+Host);
Run Code Online (Sandbox Code Playgroud)
它正常工作......发生了什么事?!
编辑::我在'如果CheckPOPHost = true然后'行中收到错误.由于某些未知原因,它会给出访问冲突错误.
您正在从线程调用非线程安全的VCL方法.
Form1.Memo1.Lines.Append('Valid HOST:: '+Host);
Run Code Online (Sandbox Code Playgroud)
永远不要那样做.
将呼叫包裹在一个Synchronize( YourThread.SendString); 线程中的方法.
例:
MyThread.SendString;
begin
Form1.Memo1.Lines.Append('Valid HOST:: '+Host);
end;
Run Code Online (Sandbox Code Playgroud)
在你的线程中的某个地方执行:
if CheckPOPHost = true then
begin
Synchronize(SendString);
Run Code Online (Sandbox Code Playgroud)
更新2:
从您关于释放对象的注释中CheckPOPHost:try..finally围绕这些对象封闭块以及try..exceptCheckPopHost中的其他块.
更新
出现了关于评论中的线程向导的讨论.如果您在向导界面后创建一个线程单元,那么这就是您所获得的:
unit Unit21;
interface
uses
System.Classes;
type
TMYTHREADTEST = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;
implementation
{
Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure TMYTHREADTEST.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end;
or
Synchronize(
procedure
begin
Form1.Caption := 'Updated in thread via an anonymous method'
end
)
);
where an anonymous method is passed.
Similarly, the developer can call the Queue method with similar parameters as
above, instead passing another TThread class as the first parameter, putting
the calling thread in a queue with the other thread.
}
{ TMYTHREADTEST }
procedure TMYTHREADTEST.Execute;
begin
{ Place thread code here }
end;
end.
Run Code Online (Sandbox Code Playgroud)
你在打电话
SockStream.Free
Run Code Online (Sandbox Code Playgroud)
即使您没有输入创建SockStream的块.这意味着您的代码可以在未初始化的变量上调用Free.这是我可以看到访问冲突的唯一原因.你需要在if块中移动Free.
另外,在创建对象时始终使用try/finally:
SockStream := TWinSocketStream.Create (MySocket.Socket, 1000);
try
....
finally
SockStream.Free;
end;
Run Code Online (Sandbox Code Playgroud)
如果你这样编写它,编译器就不会让你把Free放在错误的块中.
你应该对MySocket做同样的事情.
并且不要从线程访问GUI,但我认为其他人已经明确地说明了这一点!
| 归档时间: |
|
| 查看次数: |
948 次 |
| 最近记录: |