gpt4 book ai didi

multithreading - 主应用程序使用idPop3锁定以检索邮件消息(即使在线程中)

转载 作者:行者123 更新时间:2023-12-03 19:32:08 28 4
gpt4 key购买 nike

我正在使用一个线程来访问pop3帐户并检索消息。它工作正常,但会锁定我的应用程序,直到完成为止。无法移动窗口,关闭,单击按钮,什么也没有。

它运行良好,并允许我访问主应用程序,直到我注释掉为止(或在IdPOP31.Connect()之后)。

//获取服务器拥有的消息数

然后锁定

procedure TPopThread.Pop;
var
vName, vEmail, vServerIn, vServerOut, vUserId, vPassword: String;
vPop3Port, vSMTPPort, vSSL: String; vHTML: TStringList;
MsgCount : Integer;
i,j : Integer;
FMailMessage : TIdMessage;
begin
with frmMain do
begin
RzMemo1.Lines.Clear;
vHTML:= TStringList.Create;
GetAccount(lbxMain.SelectedItem,vName, vEmail, vServerIn, vServerOut, vUserId, vPassword,
vPop3Port, vSMTPPort, vSSL, vHTML);
IdPOP31.Host := vServerIn;
IdPOP31.Username := vUserId;
IdPOP31.Password := vPassword;
IdPOP31.Port := StrToInt(vPop3Port);

try
Prepare(IdPOP31);
IdPOP31.Connect();
// {
// //Getting the number of the messages that server has.
// MsgCount := IdPOP31.CheckMessages;
// for i:= 0 to Pred(MsgCount) do
// begin
// try
// FMailMessage := TIdMessage.Create(nil);
// IdPOP31.Retrieve(i,FMailMessage);
// RzMemo1.Lines.Add('=================================================');
// RzMemo1.Lines.Add(FMailMessage.From.Address);
// RzMemo1.Lines.Add(FMailMessage.Recipients.EMailAddresses);
// RzMemo1.Lines.Add(FMailMessage.Subject);
// RzMemo1.Lines.Add(FMailMessage.Sender.Address);
// RzMemo1.Lines.Add(FMailMessage.Body.Text);
//
// for J := 0 to Pred( FMailMessage.MessageParts.Count ) do
// begin
// // if the part is an attachment
// if ( FMailMessage.MessageParts.Items[ J ] is TIdAttachment) then
// begin
// RzMemo1.Lines.Add('Attachment: ' + TIdAttachment(FMailMessage.MessageParts.Items[J]).Filename);
// end;
// end;
// RzMemo1.Lines.Add('=================================================');
// finally
// FMailMessage.Free;
// end;
// RzMemo1.Clear;
// end;
// }
finally
IdPOP31.Disconnect;
vHTML.Free;
end;
end;
end;

它实际上是在添加线程之前完成的,因此它与注释掉的部分(而不是线程)有关

我做错了什么或没有做什么?

这是我的执行
procedure TPopThread.Execute;
begin
try
Synchronize(Pop);
except
on Ex: Exception do
fExceptionMessage := Ex.Message;
end;
end;

这就是我的称呼
PopThread := TPopThread.Create(lbxMain.SelectedItem, frmMain.DonePopping);

最佳答案

您正在自己锁定应用程序,因为synchronizing是对pop方法的调用。

Synchronize causes the call specified by AMethod to be executed using the main thread, thereby avoiding multithread conflicts.

The current thread is passed in the AThread parameter.

If you are unsure whether a method call is thread-safe, call it from within the Synchronize method to ensure it executes in the main thread. Execution of the current thread is suspended while the method executes in the main thread.



因此,出于实际目的,您就像没有多余的线程一样,因为所有代码都在主线程中执行。

An example of when you would want to use Synchronize is when you want to interact with a VCL component



另一方面,由于您直接从方法中访问许多可视控件,并且VCL也不是线程安全的,因此您必须在主线程中执行方法。

最好的办法是通过不访问线程中的任何VCL组件,而是将所有输入和输出值收集到内存中,并在线程启动之前和之后从主线程中设置/读取它,来使线程独立于VCL。线程完成。

或者,如果出于任何原因您不想这样做,则可以剖析您的方法以分离需要访问VCL的部分,并仅同步那些部分,例如:
type
TPopThread = class
private
FMailMessage : TIdMessage; //now the message belongs to the class itself

...
public
//all the values are passed via constructor or the thread is
//created in suspended state, configured and then started
property Host: string read FHost write FHost;
property UserName: string read FUserName write FUserName;
property Password: string read ...;
property Port: Integer read ...;
end;

procedure TPopThread.CopyMailToGUI;
var
J: Integer;
begin
frmMain.RzMemo1.Lines.Add('=================================================');
frmMain.RzMemo1.Lines.Add(FMailMessage.From.Address);
frmMain.RzMemo1.Lines.Add(FMailMessage.Recipients.EMailAddresses);
frmMain.RzMemo1.Lines.Add(FMailMessage.Subject);
frmMain.RzMemo1.Lines.Add(FMailMessage.Sender.Address);
frmMain.RzMemo1.Lines.Add(FMailMessage.Body.Text);

for J := 0 to Pred( FMailMessage.MessageParts.Count ) do
begin
// if the part is an attachment
if ( FMailMessage.MessageParts.Items[ J ] is TIdAttachment) then
begin
frmMain.RzMemo1.Lines.Add('Attachment: ' + TIdAttachment(FMailMessage.MessageParts.Items[J]).Filename);
end;
end;
frmMain.RzMemo1.Lines.Add('=================================================');
end;

procedure TPopThread.Pop;
var
MsgCount : Integer;
i,j : Integer;
Pop: TIdPOP3;
begin
Pop := TIdPOP3.Create(nil);
try
Pop.Host := FHost;
Pop.Username := FUserName;
Pop.Password := FPassword;
Pop.Port := FPort;
Prepare(Pop);
Pop.Connect();
//Getting the number of the messages that server has.
MsgCount := Pop.CheckMessages;
for I := 0 to Pred(MsgCount) do
begin
try
FMailMessage := TIdMessage.Create(nil);
try
IdPOP31.Retrieve(i,FMailMessage);
Synchronize(CopyMailToGUI);
finally
FMailMessage.Free;
end;
end;
finally
Pop.Free;
end;
end;

procedure TPopThread.Execute;
begin
//no need of a try/except, if an exception occurs, it
//is stored in the FatalException property
Pop;
end;

现在,您的线程将要求主线程仅将已处理的消息复制到VCL。在该复制期间,您的线程将被阻塞,并且您的应用程序将不会响应消息,因为主线程处于繁忙状态,但这将间隔很短的时间,因此即使不是理想的情况,我也认为它可以满足您的需求。

关于multithreading - 主应用程序使用idPop3锁定以检索邮件消息(即使在线程中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15138529/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com