TNMSMTP多线程发信的问题(100分)

  • 主题发起人 DreamTiger
  • 开始时间
D

DreamTiger

Unregistered / Unconfirmed
GUEST, unregistred user!
我在线程内创建TNMSMTP控件,读取配置,发送文件。当我同时创建了
两个线程,读取配置中的SMTP服务器如果相同,两个线程可以同时工作,
同时发信。但如果配置中的SMTP服务器不一样,两个线程就会有冲突,
必须一个结束了另一个才能继续。这是怎么回事?有什么解决办法?
 
能不能贴出代码来?
 
TSendMailThread = class(TThread)
private:
FromUser: string;
tslFileNames: TStringList;

SMTP1: TNMSMTP;
procedure Send;
protected
procedure Execute;override;
public
constructor Create( theFromUser:string;
theTslFileNames:TStringList);
destructor Destroy; override;
end;

constructor TSendMailThread.Create( theFromUser:string;
theTslFileNames:TStringList);
begin
inherited Create(true);

FromUser := theFromUser;
tslFileNames := TStringList.Create;

for i := 0 to theTslFileNames.Count - 1 do
if FileExists(theTslFileNames.Strings) then
tslFileNames.Add(theTslFileNames.Strings);

SMTP1 := TNMSMTP.Create(Application);

FreeOnTerminate := true;
end;

destructor TSendMailThread.Destroy;
begin
if (SMTP1.Connected) then
try
SMTP1.Abort;
SMTP1.Disconnect;
Application.ProcessMessages;
except
end;

SMTP1.Free;

inherited Destroy;
end;

procedure TSendMailThread.Send;
var
i,j: integer;
FileName,Buffer, FirstFileName : String;
F : TextFile;
SendCount,TotalCount:integer;
bError:boolean;
begin
SMTP1.Host := RegIniFile.ReadString('User/'+FromUser, 'SmtpServer' , '');
SMTP1.UserID := RegIniFile.ReadString('User/'+FromUser, 'POP3Account', '');
SMTP1.Port := RegIniFile.ReadInteger('User/'+FromUser, 'SmtpPort', 25);
SMTP1.TimeOut := RegIniFile.ReadInteger('Options', 'TimeOut', 60)*1000;

try
SMTP1.Connect;//如果第一个进程跟第二个进程的SMTP Server不一样,
//第二个进程就会停在这里不动,直到第一个进程结束。
except
if(SMTP1.Connected) then
try
SMTP1.Abort;
SMTP1.DisConnect;
Application.ProcessMessages;
except
end;

ShowMessage('错误:连接到SMTP服务器'+SMTP1.Host+'出错!');
exit;
end;

......
后面就是根据tslFilenames读取信件,发送信件,都正常
end;

procedure TSendMailThread.Execute;
begin
if(tslFileNames.Text <> '') then Synchronize(Send);
end;

下面是调用:根据不同的CurrentUserName,决定不同的发送文件列表(List),
调用进程:
try
with TSendMailThread.Create(CurrentUserName,List) do
begin
OnTerminate := nil;
Resume;
end;
except
on E: Exception do ShowMessage(E.Message);
end;
如果CurrentUserName一个为sqh一个为DreamTiger,而且两个用户的SMTP不一样,
从程序可以看到,进程中的SMTP1.Host就不一样,这时候就会出现上面说的情况,
进程2会等待进程1结束后再继续运行。如果进程1时间很长,可能导致进程2超时出错。
 
以下是个人愚见:

因为 PORT 只有一个, 所以不能同时执行两个线程.
当你的 USERNAME,SERVER NAME 是同一时, 你的两个线程能收到
SERVER 的 回应信息, 故能执行.
当你的 USERNAME,SERVER NAME 是不同时, 你的另一线程不能收到
SERVER 的 回应信息,(因为PORT 被占用) 故不能正常执行.

如有兴趣, 可款本人的 THREAD 问题. (在 已答问题中)
 
guo_qpeter:我有点不明白:port是跟服务器有关吧,跟我本地运行程序的port
有什么关系?我又不用本地port发信的了。
 
我与guo_qpeter的意见相仿!
 
CLIENT 这边也有 PORT 啊!
THREAD 的程序我周一发给你,你可不要食言哦!
 
guo_qpeter:说过的话是不会食言的,你放心。
如果说是client端的port起的作用,那么,为什么收信的时候,
可以同时从几个POP3服务器收信,不起冲突?是不是pop3跟smtp在原理上有
什么不一样?
 
可是我总怀疑是tstringlist冲突的问题.
按理说,client端不用关心port的.
 
cAkk:如果是TStringList的问题,那也不对啊,我并没有在Execute中用到
传递参数的TStringList啊?我是在进程内建立一个tslFileList,把
传递过来的FileName赋给了tslFileList。而且,我是用inherit Create
(True)的,也就是说在主程序中,必须Resume才能执行的,这个时候,
Create已经完成了,execute的时候,跟Create参数已经没有任何关系了。
 
你去但一个SAKMAIL的空间,里头有 POP3 / SMTP 的协议原理.
目前我的机上没有. (换了一台)
我发给你的程序你试了吗?
不好意思我在公司无法用中文.
 
我知道怎么回事了,呵呵。是由于Synchronize的错误用法造成的。
今天看书的时候才发现,Synchronize其实是把子线程暂时模拟为
主线程来运行,这个时候,就不允许其他子线程的运行了。第二个
TSendMailThread就一直在等待,知道Synchronize结束。一个教
训啊。Synchronize只是用于需要对VCL控件进行操作的地方,不能
乱用的。

分数是不能取回了,大家分了吧。
 
顶部