我无法弄清楚如何以最佳方式解决这个问题。
现在我有一个Windows服务,其唯一任务是从具有特定DSN的数据库中收集数据,然后在数据有效时发送电子邮件。该服务包含一个计时器,每5分钟计时一次,并执行上述任务。
现在我需要重新编写Windows服务才能在1个以上的DSN上运行。 我想在windows服务中创建几个线程,然后在每个线程内再次有一个seperat计时器。 这是一个好主意,如何做到这一点?我想避免为每个DSN提供Windows服务。
如果我没有任何意义,我会尝试绘制它
Windows Service
线程1(DSN1)-----------------------------线程2(DSN2)---------- ------------ Thread3(DSN3)
计时器(每X分钟刻度)-----------------计时器(相同)---------------------- ---定时器(相同)
逻辑()---------------------------------------------逻辑电--------------------------------逻辑()
希望我的问题有道理:))
答案 0 :(得分:6)
据我所知,每个计时器代表一个独立的线程。知道了这一点,我会尝试为每个给定的dsn动态创建计时器对象。
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
private List<GetDataFromDSN> list = null;
protected override void OnStart(string[] args)
{
list = new List<GetDataFromDSN>();
// 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();
}
}
答案 1 :(得分:4)
每个DSN都需要在一个单独的线程上吗?
如果要在线程调用的某种服务中封装电子邮件检索和验证逻辑,则可以从调度线程中隐藏多个DSN的事实。例如,IEmailService
可能有以下合同:
public interface IEmailService
{
void SendEmailsToValidAddresses();
}
并且实现可能如下所示:
public class MultipleSourcesEmailService : IEmailService
{
private IEnumerable<IDatabaseSource> databases;
public EmailService(params IDatabaseSource[] sources)
{
databases = new List<IDatabaseSource>(sources);
}
public void SendEmailsToValidAddresses()
{
foreach(var database in databases)
{
var emailAddresses = database.SelectAllEmailAddresses();
ValidateAndSendEmailsTo(emailAddresses);
}
}
public void ValidateAndSendEmailsTo(IEnumerable<string> emailAddresses)
{
// Perform appropriate logic
...
}
}
通过这种方式,您的计时器逻辑可以在单个线程上保持不变,而发送电子邮件的问题则分为IEmailService
。这也意味着您可以实现SingleSourceEmailService
和MultipleSourceEmailService
并在代码完成时交换多个来源,并且服务的使用者永远不会知道。
当然,上面实现的EmailService将顺序地从多个源发送SendEmails - 如果您需要它并行运行,您可以更改EmailService以为您拥有的每个DSN启动新线程,甚至可以调用它是:MultiThreadedMultipleSourceEmailService
但作为IEmailService的使用者,您的日程安排永远不会知道其中的差异。
答案 2 :(得分:1)
使用背景工作者。 http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
为每个DSN启动一个,非常流畅且易于使用。
答案 3 :(得分:0)
以下是我的项目中的示例代码,希望这有帮助
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
}