对于实现线程化电子邮件发送队列的类,设计会是什么样子?

时间:2015-06-11 11:06:46

标签: multithreading delphi delphi-xe7 omnithreadlibrary

所以我的应用程序是一个出租车呼叫调度系统,其中操作员通过电话接收呼叫并将接到的呼叫分配给驾驶员。在输入呼叫详细信息的“呼叫详细信息”表单中,单击“保存”按钮后,表单应该关闭,应该在后台线程中向出租车司机发送电子邮件,并显示主表单,他可以在选择下一个呼叫并将其分配给另一个驱动程序。

关于设计的一点点是它应该是一个队列,这意味着队列中的电子邮件需要等到处理正在发送的电子邮件完成。当然,电子邮件发送发生在与主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.

1 个答案:

答案 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>