[英]Timer within Thread within Windows Service
我無法弄清楚如何以最好的方式解決這個問題。
現在我有一個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<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();
}
}
每個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的使用者,您的調度永遠不會知道其中的區別。
使用背景工作者。 http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
只需為每個DSN啟動一個,非常流暢且易於使用。
這是我的項目中的示例代碼,希望這會有所幫助
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
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.