所以我的应用程序是一个出租车呼叫调度系统,其中操作员通过电话接收呼叫并将接到的呼叫分配给驾驶员。在输入呼叫详细信息的“呼叫详细信息”表单中,单击“保存”按钮后,表单应该关闭,应该在后台线程中向出租车司机发送电子邮件,并显示主表单,他可以在选择下一个呼叫并将其分配给另一个驱动程序。
关于设计的一点点是它应该是一个队列,这意味着队列中的电子邮件需要等到处理正在发送的电子邮件完成。当然,电子邮件发送发生在与主VCL线程不同的线程中。
通过从主线程到电子邮件线程的函数调用,只有对主线程的响应才会是队列中剩余要发送的电子邮件数。例如。如果用户试图关闭应用程序,它将询问电子邮件队列类,以确定队列中是否有待处理的电子邮件。
在Delphi中,哪种类设计和构造最能实现此功能?我确定它有一个或多个TThreads,但我失去了它。我本来可以开始写一些东西了,但我确定它会出错,我需要拆开它,在这里发布并根据建议重新开始。这就是我首先在这里发布的原因 - 我想要设计技巧。由于我使用Delphi,我在这里发布是因为我想要特定于Delphi的设计技巧。提前感谢您的任何答案。
注意:我可以使用TThread实现或OmniThreadLibrary。
我包括课程的基本模板,答案需要扩展和构建。
unit uEmailQueue;
interface
uses Classes;
type
TEmailServer = record
SMTPHost: String;
SMTPPort: Integer;
SMTPUseSSL: Boolean;
SMTPUserName: String;
SMTPPassword: String;
SMTPSenderName: String;
end;
TEmailMessage = record
RecipientEmailAddr: String;
EmailSubject: String;
EmailMessage: String;
end;
TEmailQueue = class(TObject)
private
FEmailServer: TEmailServer;
public
procedure SendEmail(AEmailMessage: TEmailMessage);
end;
implementation
{ TEmailQueue }
procedure TEmailQueue.SendEmail(AEmailMessage: TEmailMessage);
begin
end;
end.
答案 0 :(得分:1)
我建议你设置OTL。
你最有可能拥有唯一的SMTP服务器,所以唯一的邮件发送线程,以防你以后添加更多通知发送服务器(如向不同的电话运营商发送短信) - 你会添加更多的外发"水槽"线程。
就个人而言,我会考虑使用Pipeline模式。
现在它看起来主要是过度工程,但它稍后会为您提供自定义和扩展(比如添加更多通知方式而不是发送电子邮件,例如记录流程,例如添加" VIP客户端/常规客户/阴暗客户/欺诈"启发式)或其他任何事情。
由于Pipeline以一些线程安全的源数据集合/容器启动,要开始处理新请求,您只需要将任务记录放入该队列。
像
这样的东西 var TaxiInQueue: iOmniBlockingCollection;
....
var NewTask: TEmailMessage;
...
TaxiInQueue.Add( TOmniValue.FromRecord(NewTask) );
同样,这将使您能够从单线程GUI应用程序(使用单个代理放入新任务)扩展到网络代理(3层或WWW-servlet),其中多个线程同时从不同的连接输入新任务/线程。
只有对主线程的回复才会是队列中剩余的电子邮件数量
就我个人而言,我会用"双重会计"方式,我会保留两个变量:创建的总任务和完成的总任务。它们可以通过主线程中的单独的不可见窗口(AllocateHWND和使用PostMessage来触发增量)来管理,或者可以通过单独的工作线程(可能过度工程)来管理,或者只是一些具有任何类型的MREW锁定的对象。 / p>
delta是当前(或稍微过时)的队列长度。此外,windows / thread / object将能够生成自己的事件(如果队列处于空闲,正常或溢出时绘制一些米)
关于MREW锁,在Delphi RTL中有一个库存,在OTL库本身还有另一个,并且有一些人将OmniMREW移植到Lzarus,然后再做一个他声称更有效的锁。 / p>