Windows服务中线程内的计时器

我无法弄清楚如何以最好的方式解决这个问题。

现在我有一个Windows服务,其唯一任务是从具有特定DSN的数据库中收集数据,然后在数据有效时发送电子邮件。 该服务包含一个计时器,每5分钟计时一次,并执行上述任务。

现在我需要重新编写Windows服务才能在1个以上的DSN上运行。 我想在windows服务中创建几个线程,然后在每个线程内再次有一个seperat计时器。 这是一个好主意,如何做到这一点? 我想避免为每个DSN提供Windows服务。

如果我没有任何意义,我会尝试绘制它

Windows Service 

线程1(DSN1)—————————–线程2(DSN2)————- ——— Thread3(DSN3)
定时器(每X分钟刻度)—————–定时器(相同)———————- —定时器(相同)
逻辑()———————————————逻辑电 – – – – – – – – – – – – – – – – 逻辑()

希望我的问题有道理:)

据我所知,每个计时器代表一个独立的线程。 知道了这一点,我会尝试为每个给定的dsn动态创建计时器对象。

 public partial class Service1 : ServiceBase { public Service1() { InitializeComponent(); } private List list = null; protected override void OnStart(string[] args) { list = new List(); // assume args contains your given dsn values foreach (string dsn in args) { GetDataFromDSN newObj = new GetDataFromDSN(); newObj.DSN = dsn; list.Add(newObj); newObj.Start(); } } } public class GetDataFromDSN { public string DSN { get; set; } private Timer timer = null; private double interval = 1000*60*5; // 5 minutes interval public GetDataFromDSN() { // init your object timer = new Timer(interval); timer.Elapsed +=new ElapsedEventHandler(timer_Elapsed); } private void timer_Elapsed(object sender, ElapsedEventArgs e) { // do what ever you want } public void Start() // or even make timer public { timer.Start(); } public void Stop() { timer.Stop(); } } 

每个DSN都需要在一个单独的线程上吗?

如果您要在线程调用的某种服务中封装电子邮件检索和validation逻辑,则可以从调度线程中隐藏有多个DSN的事实。 例如, IEmailService可能具有以下合同:

 public interface IEmailService { void SendEmailsToValidAddresses(); } 

并且实现可能看起来像这样:

 public class MultipleSourcesEmailService : IEmailService { private IEnumerable databases; public EmailService(params IDatabaseSource[] sources) { databases = new List(sources); } public void SendEmailsToValidAddresses() { foreach(var database in databases) { var emailAddresses = database.SelectAllEmailAddresses(); ValidateAndSendEmailsTo(emailAddresses); } } public void ValidateAndSendEmailsTo(IEnumerable emailAddresses) { // Perform appropriate logic ... } } 

通过这种方式,您的计时器逻辑可以保持相同并且在单个线程上,而发送电子邮件的问题则分离到IEmailService 。 这也意味着您可以实现SingleSourceEmailServiceMultipleSourceEmailService并在代码完成时交换多个源,并且服务的使用者不需要知道。

当然,上面实现的EmailService将按顺序从多个源发送SendEmails – 如果您需要它并行运行,您可以更改EmailService以为您拥有的每个DSN启动新线程,您甚至可以将其命名为: MultiThreadedMultipleSourceEmailService但作为IEmailService的使用者,您的调度永远不会知道其中的区别。

使用背景工作者。 http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

只需为每个DSN启动一个,非常流畅且易于使用。

尝试使用System.Threading.Timer

这是我的项目中的示例代码,希望这会有所帮助

 public void StartDSNTimers() { _tmr1 = new Timer(CheckMessages, dsn1, 0, 60000); _tmr2 = new Timer(CheckMessages, dsn2, 0, 60000); _tmr3 = new Timer(CheckMessages, dsn3, 0, 60000); } private void CheckMessages(object obj) { //Logic }