3

現時点では、一連の Windows サービスを C# で開発しています。これは、タイマー (からSystem.Timers) を使用して実行中のマシンをポーリングし、統計をリモート リスナーに報告します (リモート マシンは WCF データ サービスをホストします)。

セットアップは次のとおりです。 System.Timers.Timer を追加機能でラップするクラスがあり、タイマーが経過して情報をログに記録するときに発生する汎用イベント ハンドラーを受け入れます。

public class GenericPoller
{
    private EventLog _log;
    private string _componentName;
    private System.Timers.Timer _timer;

    public GenericPoller
        (
            double interval, 
            System.Timers.ElapsedEventHandler handler, 
            EventLog log,
            string componentName
        )
    {
        _componentName = componentName;
        _log = log;

        _timer = new System.Timers.Timer();
        _timer.Interval = interval;
        _timer.AutoReset = true;
        _timer.Enabled = false;
        _timer.Elapsed += handler;
    }

    public void StartPolling()
    {
        try
        {
            _timer.Enabled = true;
            _log.WriteEntry
            (
                "Timer started for component '" + _componentName
                + "', with " + _timer.Interval + "ms interval."
            );
        }
        catch
        {
            _log.WriteEntry("Failed to start timer for component '" + _componentName + "'.");
        }
    }

    public void StopPolling()
    {
        try
        {
            _timer.Enabled = false;
            _log.WriteEntry("Timer stopped for component '" + _componentName + "'.");
        }
        catch
        {
            _log.WriteEntry("Failed to stop timer for component '" + _componentName + "'.");
        }
    }

}

私が実装しているサービスのいずれかは、GenericPollerコンストラクターで を作成し、別のスレッドを介してOnStart呼び出すメソッドで、StartPollingこのメソッド内でできるだけ時間を消費しないようにします。サービスクラスはおおよそ次のようになります。

public partial class CPUMonitor : ServiceBase
{
    private GenericPoller _poller;
    Thread _thread;

    public CPUMonitor()
    {
        InitializeComponent();

        _poller = new GenericPoller
        (
            HardwareMonitorCommon.Instance.DefaultPollingInterval,
            PollCPU,
            EventLog,
            "CPUMonitor"
        );
    }

    protected override void OnStart(string[] args)
    {
        _thread = new Thread(new ThreadStart(_poller.StartPolling));
        _thread.Start();
    }

    protected override void OnStop()
    {
        _poller.StopPolling();
        _thread.Join();
    }

    private void PollCPU(object sender, System.Timers.ElapsedEventArgs e)
    {

            Code to aqcuire CPU stats and report to WCF data service...
    }
}

コマンドでサービスをインストールしますinstallutil.exe。割り当てられた時間内にサービスを開始できない場合があります (エラー 1053) が、この問題のパターンはないようです。起動に失敗するのは、10 回中 4 回程度です。

なぜこれが起こるのか理解できません。システム/アプリケーション イベント ログは、サービス プロセスからのエラーや例外を報告しません。また、すべての「重い作業」が別のスレッドで行われている場合にタイムアウトが発生する理由がわかりません。

私は決してマルチスレッドコードを書くプロ/エキスパートではないので、何か間違ったことをしていると完全に予想しています...それが何であるかわかりません...


編集:Mainメソッドは自動生成されたファイルに残り、Program.cs実行されるコンポーネントを追加するために変更しただけです:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new CPUMonitor(),
            new MemoryMonitor()
        };
        ServiceBase.Run(ServicesToRun);
    }
}
4

0 に答える 0