簡體   English   中英

Windows服務中線程內的計時器

[英]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 這也意味着您可以實現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
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM