Таймер в потоке в службе Windows - PullRequest
4 голосов
/ 06 декабря 2011

Я не могу понять, как лучше решить эту проблему.

Сейчас у меня есть служба Windows, единственной задачей которой является сбор данных из базы данных с конкретным DSN, а затем отправка по электронной почтеесли данные действительны.Служба содержит таймер, который срабатывает каждые 5 минут и выполняет указанные выше задачи.

Теперь мне нужно переписать службу Windows, чтобы иметь возможность работать более чем на 1 DSN.Я думал сделать несколько потоков внутри службы Windows, а затем снова иметь отдельный таймер внутри каждого потока.Это хорошая идея и как это можно сделать?Я хочу избежать использования службы Windows для каждого DSN.

Я постараюсь нарисовать его, если я не вижу смысла

                             Windows Service

Thread1 (DSN1) ----------------------------- Резьба2 (dsn2) ---------------------- Thread3 (DSN3)
Таймер (тикает каждые X минут) ----------------- Таймер (такой же) ------------------------- Таймер (такой же)
Логика () --------------------------------------------- Logic --------------------------------- Logic ()

Надеюсь, моя проблема имеет смысл:)

Ответы [ 4 ]

6 голосов
/ 06 декабря 2011

Насколько я знаю, каждый таймер представляет собой отдельный поток.Зная это, я бы попытался динамически создавать объекты таймера для каждого данного 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();
    }
}
4 голосов
/ 06 декабря 2011

Должен ли каждый из уведомлений о доставке находиться в отдельном потоке?

Если бы вы должны были инкапсулировать логику поиска и проверки электронной почты в какую-то службу, которую вызывал поток, тот факт, что было несколько уведомлений о доставкеможет быть скрыт от потока планирования.Например, 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 asреализованный выше будет отправлять SendEmails из нескольких источников последовательно - если вам нужно, чтобы он работал параллельно, вы можете изменить EmailService для запуска нового потока для каждого из имеющихся у вас DSN, вы можете даже назвать его: MultiThreadedMultipleSourceEmailService, но какПотребитель IEmailService ваш график никогда не будет знать разницу.

1 голос
/ 06 декабря 2011

Используйте фонового работника. http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

Просто начните один для каждого DSN, очень плавный и простой в использовании.

0 голосов
/ 06 декабря 2011

Попробуйте использовать 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
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...