Я создаю Службу Windows, используя System.Timers.Timer
. Задачи, рассчитанные делегатом таймера, могут занимать от нескольких секунд до нескольких минут. Я хотел бы убедиться, что, когда служба остановлена, все делегированные потоки, выполняющиеся в настоящее время, завершаются, прежде чем будут удалены.
Вот код, однако он не выполняет то, что я ожидаю, поскольку запущенные в данный момент потоки никогда не завершаются, если служба Windows остановлена во время их работы.
public abstract class AgentServiceBase : ServiceBase
{
private System.ComponentModel.IContainer components = null;
private System.Timers.Timer _Timer;
private string _logPath;
private const int MAXNUMBEROFTHREADS = 10;
protected int interval = 25000;
protected int numberOfAllowedThreads = 2;
public AgentServiceBase()
{
this.InitializeComponent();
this._logPath = (Path.GetDirectoryName(Assembly.GetAssembly(this.GetType()).CodeBase)).Substring(6).Replace("/", @"\");
}
protected override void OnStart(string[] args)
{
if (args.Length > 0)
{
int.TryParse(args[0], out interval);
}
if (args.Length > 1)
{
int.TryParse(args[1], out numberOfAllowedThreads);
if (numberOfAllowedThreads > MAXNUMBEROFTHREADS)
{
numberOfAllowedThreads = MAXNUMBEROFTHREADS;
}
if (numberOfAllowedThreads == 1)
{
numberOfAllowedThreads = 2;
}
}
ThreadPool.SetMaxThreads(numberOfAllowedThreads, numberOfAllowedThreads);
this._Timer = new System.Timers.Timer();
this._Timer.Elapsed += new ElapsedEventHandler(PollWrapper);
this._Timer.Interval = this.interval;
this._Timer.Enabled = true;
}
protected override void OnStop()
{
this._Timer.Enabled = false;
Process currentProcess = Process.GetCurrentProcess();
foreach (Thread t in currentProcess.Threads)
{
t.Join();
}
}
/// <summary>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
this.ServiceName = "Agent Service - Johnhenry";
}
private void PollWrapper(object sender, ElapsedEventArgs e)
{
try
{
this.Poll(sender, e);
}
catch (Exception exception)
{
string message = this.GetType().FullName + " - Windows Service Exception\n";
message += exception.GetNestedExceptionInSingleStringOutput();
FileHelper.Log(message, this._logPath, "exception", FileHelper.LogFileNameChangeFrequency.DAYLY);
}
}
protected abstract void Poll(object sender, ElapsedEventArgs e);
}
Большое спасибо,
Giuseppe
UPDATE
После нескольких разных попыток подсчета собственных потоков текущего процесса я в итоге остановился на более простом решении, использующем счетчик потоков, которые таймер инициировал и все еще работает. Исходя из этого, я вызываю Sleep
в главном потоке и выдаю RequestAdditionalTime
, пока все потоки не закончатся.
Следуя пересмотренным 2 методам:
protected override void OnStop()
{
this._Timer.Enabled = false;
while (numberOfRunningThreads > 0)
{
this.RequestAdditionalTime(1000);
Thread.Sleep(1000);
}
}
private void PollWrapper(object sender, ElapsedEventArgs e)
{
numberOfRunningThreads++;
try
{
this.Poll(sender, e);
}
catch (Exception exception)
{
string message = this.GetType().FullName + " - Windows Service Exception\n";
message += exception.GetNestedExceptionInSingleStringOutput();
FileHelper.Log(message, this._logPath, "exception", FileHelper.LogFileNameChangeFrequency.DAYLY);
}
finally
{
numberOfRunningThreads--;
}
}