Я создаю свою первую службу Windows. Это компонент, который подключается к почтовому ящику и загружает все письма и сохраняет их на моем локальном диске.
Мои вопросы таковы.
Каков наилучший способ повторить вызов программы в службе С# windows. Я думаю об использовании простого таймера? С чего начать и остановить таймер? это в самом сервисе или в программе, на которой работает моя служба?
Какой код должен быть включен в службу Windows для следующей функции
protected override void OnStart(string[] args)
{
//timer?
// MyProgram mp = new MyProgram();
}
Должен ли я просто запустить приложение с новым экземпляром, например, выше, или мне нужно добавить больше вещей?
Как я уже сказал, это мой первый раз для использования служб Windows.
EDIT:
Спасибо за ответы на все вопросы. Конечно, есть много разных способов сделать это, но я нашел, что лучший способ для меня - это один знак в качестве решения.
Спасибо за любую помощь!
Здесь шаблон, который вы можете использовать, обрабатывает проблемы с повторной попыткой с использованием таймера.
public partial class Service : ServiceBase{
System.Timers.Timer timer;
public Service()
{
timer = new System.Timers.Timer();
//When autoreset is True there are reentrancy problme
timer.AutoReset = false;
timer.Elapsed += new System.Timers.ElapsedEventHandler(DoStuff);
}
protected override void OnStart(string[] args)
{
timer.Interval = 1;
timer.Start();
}
private void DoStuff(object sender, System.Timers.ElapsedEventArgs e)
{
Collection stuff = GetData();
LastChecked = DateTime.Now;
foreach (Object item in stuff)
{
item.Dosomthing(); //Do somthing should only be called once
}
TimeSpan ts = DateTime.Now.Subtract(LastChecked);
TimeSpan MaxWaitTime = TimeSpan.FromMinutes(5);
if (MaxWaitTime.Subtract(ts).CompareTo(TimeSpan.Zero) > -1)
timer.Interval = MaxWaitTime.Subtract(ts).Milliseconds;
else
timer.Interval = 1;
timer.Start();
}
OnContinue OnPause и OnStop мелодично просты в разработке.
protected override void OnPause()
{
base.OnPause();
this.timer.Stop();
}
protected override void OnContinue()
{
base.OnContinue();
this.timer.Interval = 1;
this.timer.Start();
}
protected override void OnStop()
{
base.OnStop();
this.timer.Stop();
}
Я использую AutoResetEvent с таймаутом:
while(!autoResetEvent.WaitOne(MY_MILLISECOND_WAIT))
{
// do something
}
И когда я хочу остановиться, я просто устанавливаю autoResetEvent
.
Таймер вреден для нескольких причин: Reentry.
OnStart(string[] args)
создаст autoResetEvent
.
Вот моя реализация его как PollingWorker
:
public class PollingWorker : IDisposable
{
private const int DEFAULT_INTERVAL_MS = 1000; // 1 second
private const int WAIT_INTERVAL = 20; // MS
private Thread _labourer = null;
private int _pollingIntervalMS = DEFAULT_INTERVAL_MS;
private ParameterizedThreadStart _work = null;
private bool _working = false;
private object _state = new object();
private AutoResetEvent _resetTimer = new AutoResetEvent(false);
private bool _itsTimeToQuite = false;
private bool _poked = false;
private bool _isCurrentlyWorking = false;
public string Name
{
get { return _labourer.Name; }
set { _labourer.Name = value; }
}
public PollingWorker(int intervalMS, ParameterizedThreadStart work, object state):
this(intervalMS, work, state, Guid.NewGuid().ToString())
{
}
public PollingWorker(int intervalMS, ParameterizedThreadStart work, object state, string name)
{
_pollingIntervalMS = intervalMS;
_labourer = new Thread(new ThreadStart(TryDoingSomeWork));
_labourer.Name = name;
_work = work;
}
public int PollingIntervalMS
{
get { return _pollingIntervalMS; }
set
{
_pollingIntervalMS = value;
}
}
public void StartWork()
{
StartWork(true);
}
public void StartWork(bool initialWait)
{
_working = true;
_poked = !initialWait;
_labourer.Start();
}
public void PauseWork()
{
_working = false;
}
public void Quit()
{
Quit(int.MaxValue);
}
public void Quit(int maximumWaitToFinishCurrentWorkMS)
{
int totalWait = 0;
_itsTimeToQuite = true;
_working = false;
_resetTimer.Set();
while (_isCurrentlyWorking && Thread.CurrentThread.Name != _labourer.Name) // in case Quit is called from Work
{
Thread.Sleep(WAIT_INTERVAL);
totalWait += WAIT_INTERVAL;
if(totalWait>maximumWaitToFinishCurrentWorkMS)
break;
}
Dispose();
}
// poke to wake up !
public void Poke()
{
try
{
// if you call set on the same thread while it is not on waitOne
// it does not work
if (Thread.CurrentThread.Name == this.Name)
//_resetTimer.Set();
_poked = true;
else
_resetTimer.Set();
}
catch
{
// ignore any error with poking
}
}
private void TryDoingSomeWork()
{
while (!_itsTimeToQuite)
{
//Debug.WriteLine(string.Format("{0:ss fff}\t{1}\t{2}\t{3}", DateTime.Now, this.Name, string.Empty, string.Empty));
if (!_poked)
_resetTimer.WaitOne(_pollingIntervalMS, false);
_poked = false;
// timed-out which means timer pulse, so do some work
if (_working)
{
_isCurrentlyWorking = true;
_work(_state);
_isCurrentlyWorking = false;
}
}
}
public object State
{
get { return _state; }
set
{
lock (_state)
{
_state = value;
}
}
}
public bool Working
{
get { return _working; }
}
#region IDisposable Members
public void Dispose()
{
try
{
_resetTimer.Close();
_labourer.Abort();
}
catch
{
// dont want to raise errors now
// so ignore especially threadabortexception!!
}
}
#endregion
}
@Aliostad
.
PollingWorker
codeproject.com/KB/biztalk/Excellence.aspx
Создайте нить или что-то еще, не нужно таймера! В OnStart вы запускаете поток, а в OnStop вы можете остановить поток.