这是在一个线程中封装sakemail的代码,是iCompanion源码的一部分
虽然只使了一个线程,功能也相当简单,但原理基本就是这样了
在大范围的使用中工作相当稳定。
const
WM_SHOWNOTIFY = WM_USER + 100;
type
TMailChkThread = class(TThread)
protected
procedure execute;override;
public
MailChk:TMailCheck;
SakPOP:TSakPOP;
MailIndex:integer;
MailChkInfo:string;
MailNumber:integer;
constructor Create(MailChkObj:TMailCheck);
destructor Destroy;override;
procedure RefMailInfo;
end;
constructor TMailChkThread.Create(MailChkObj:TMailCheck);
begin
Inherited Create(True);
SakPOP := TSakPOP.Create(nil);
MailChk := MailChkObj;
end;
destructor TMailChkThread.Destroy;
begin
SakPOP.free;
SakPOP := nil;
inherited Destroy;
end;
procedure TMailChkThread.execute;
var
i,j:integer;
PassInput:string;
MailCount,LoginCount:integer;
begin
MailCount := 0;
LoginCount := 0;
for i := 0 to MailCheck.count -1 do // MailCheck是一个自定义,封装了对邮箱数据的访问
with MailChk.Items[i] do
begin
MailIndex := i;
if Enabled = false then Continue;
if Pass = '' then
begin
if NOT CInputQuery ('网络伴侣 - 请输入密码', '服务器:'+Server+ #13#10 +'用户名:'+ Login+ #13#10 +'密码:' , PassInput,true) then break
//CInputQuery 是一个自定义函数,显示输入窗体以取得输入的字符串
else Pass := PassInput;
end;
SakPOP.Host := Server;
SakPOP.Port := '110';
SakPOP.UserId := Login;
SakPOP.UserPasswd := Pass;
try
SakPOP.Connect;
if SakPOP.POPError then
begin
MailNumber := 0;
MailChkInfo := '无效的服务器';
Synchronize(RefMailInfo);
Continue;
end;
Application.ProcessMessages;
if Terminated then Break;
if not SakPOP.login then
begin
MailNumber := 0;
MailChkInfo := '无效的用户名或密码';
Synchronize(RefMailInfo);
Continue;
end;
Application.ProcessMessages;
if Terminated then Break;
SakPOP.Init;
MailNumber := SakPOP.MsgsCount;
MailChkInfo := '完成';
Synchronize(RefMailInfo);
if SakPOP.MsgsCount > 0 then
begin
inc(LoginCount);
inc(MailCount,SakPOP.MsgsCount);
end;
SakPOP.Quit;
except
MailNumber := 0;
MailChkInfo := '网络错误';
Synchronize(RefMailInfo);
break;
end;
Application.ProcessMessages;
if Terminated then Break;
end;
if MailCount > 0 then
begin
PostMessage(frmBody.Handle,WM_SHOWNOTIFY,LoginCount, MailCount);
//全部检测完成,向主窗体发送消息,主窗体做相应反应
end;
end;
procedure TMailChkThread.RefMailInfo; //更新listview
var
ListItem: TListItem;
begin
begin
ListItem := frmbody.LVMail.Items.Add;
ListItem.ImageIndex := 3;
ListItem.Caption := MailChk.Items[MailIndex].Name;
ListItem.SubItems.Add(inttostr(MailNumber));
ListItem.SubItems.Add(MailChkInfo);
end;
end;
procedure TfrmBody.btnChkMailClick(Sender: TObject); //启动检测邮件线程
var
dwExitCode:DWORD;
ThreadID:DWORD;
begin
if OnlineFlag = false then
begin
msgbox('在离线状态下不能检测邮件,请拨号上网。','提醒',MB_OK+MB_ICONINFORMATION);
exit;
end;
if ThreadMail <> nil then //取消按钮被按下
begin
ThreadMail.Terminate;
exit;
end;
btnChkMail.Caption := '取消';
LVMail.Items.Clear;
ThreadMail := TMailChkThread.Create(MailCheck);
ThreadMail.OnTerminate := frmbody.onMailTerminated;
hThread := ThreadMail.Handle;
ThreadMail.Resume;
end;
procedure TfrmBody.WMShowNofity(var Message: TMessage);
begin
ShowNotifyForm('在' + inttostr(Message.WParam) + '个信箱检测到' + inttostr(Message.LParam) + '封信件!');
end;
procedure TfrmBody.FormDestroy(Sender: TObject);
var
i:integer;
dwExitCode:DWORD;
begin
//很重要的一步,在程序退出时如果线程仍在运行,必须强行杀死该线程
if ThreadMail <> nil then
begin
ThreadMail.Suspend;
CloseHandle(ThreadMail.Handle);
end;
end;
其他大虾有例子,也请拿出来交流交流。