2009-05-15 8 views
1

私は基本的にメールボックスにアクセスして電子メールを読むWindowsサービスを持っています。私はx秒ごとにメールボックスをチェックする最善の方法を見つけようとしています。x秒ごとにWindowsサービスを呼び出す/起動する最も良い方法は何ですか?

1つの方法は、単にThread.Sleepを呼び出し、次にStartメソッドを再度呼び出すことです。

protected override void OnStart(string[] args) 
{ 
    // get config settings 
    CheckMailbox(); 
} 

public void CheckMailbox() 
{ 
    int x = 5000; 

    // do stuff 

    Thread.Sleep(x); 
    CheckMailbox(); 
} 

これが最善の方法かどうかはわかりません。さらにこれを調べるには、WCF経由でサービスを公開してWindowsサービスを呼び出すことができると私は理解します。この場合、WebアプリケーションがProcessというプロセスを呼び出して開始すると、矛盾するスレッドが存在するでしょうか?どうすればそれに対処できますか?毎回新しいスレッドを作成してキューに入れる必要がありますか?

答えて

7

睡眠は通常悪い考えです。それ以外は、ストップイベントにすばやく反応しないことを意味します。

Timerを使用してください。

は、それぞれのケースであなたは基本的にあなたがタイマー「ダニ」とあなたがそれをしたいときに毎回起こるしたいものを言う:サービスのために適切である2があります火災。

私のスレッドチュートリアルはsection explaining some of the differences between available timersです。

あなたのWCFに関する質問はよく分かりませんが、あなたのWebサービスが明示的にサービスを開始しているとは思われません.WCF経由で連絡するだけです。はい、スレッドには注意が必要です。正確には、WCFサービスが公開していることに注意する必要があります。

+0

+1 - 良い点!寝ている間、サービスはイベントを停止するために反応しません、それは本当です。 –

+0

スレッディングタイマーでは、10秒ごとにメールボックスをチェックし、開かれて処理するのに10秒以上かかると、これは一度に複数のスレッドを実行するのは正しいでしょうか? – mickyjtwin

+0

+1タイマーは便利です! @mickyjtwin:System.Timers.Timerを使用する場合はStartメソッドとStopメソッドがあるので、Stopを呼び出してメールを処理してからStartを呼び出すことができます。そうすれば、次回の確認までメールの処理が完了してからx秒待つことになります。しかし、私があなたが提案する場合には、並列スレッドを取得するとは思わない。ティックは新しいスレッドではなくタイマーが作成されたスレッドで呼び出されるべきです。 –

0

サービスとして(ログインしている人がいなくても)バックグラウンドで実行したい場合は、これを行う方法の1つです。

もう1つは、「Tick」イベントハンドラを5秒ごとに呼び出すTimerを持つことです。

チェックが頻繁ではない場合は、コマンドラインコンソールアプリケーションを作成し、Windowsで「スケジュールされたタスク」としてスケジュールすることもできます。

マルク・

0

あなたのコードは、あなたが自分自身の中からメソッドを呼び出しているため、すべてのコールの呼び出しスタックに追加するという問題があります。ある時点でスタックオーバーフロー例外が発生します。 1つのウェイトは、一定時間後に戻って通知します「待機しているスレッド」に別のメソッドを呼び出すことです:

private void CheckMailBox() 
{ 
    _waitHandle = new AutoResetEvent(true); 
    while (_waitHandle.WaitOne()) 
    { 
     // do the mail checking 
     ((IDisposable)_waitHandle).Dispose(); 
     _waitHandle = new AutoResetEvent(false); 
     ThreadPool.QueueUserWorkItem(WaitSomeTime, 2000); 
    } 

} 

private void WaitSomeTime(object state) 
{ 

    Thread.Sleep((int)state); 
    _waitHandle.Set(); 
} 
1

基本System.Threading.Timerコード:

// Class level variable in the Windows Service: 
private System.Threading.Timer timer; 

// This is in the constructor for a Windows Service. 
// interval would be the time in milliseconds in between ticks. 
// 0 is how long until it should start. 
timer = new Timer(new TimerCallback(TimerElapsed), null, 0, interval); 

// The TimerCallback in the Windows Service: 
private void TimerElapsed(object o) 
{ 
    // Do email stuff here. 
} 
0

使用して超えた可能性強化タイマーはあなたのサービスのスケジューリングコンポーネントを使用することです。その後、メールボックスにアクセスするコードのホストとしてサービスをセットアップできます。

Quartz.NETはこれを行うことができるオープンソースのスケジューリングコンポーネントです。それはあなたが望むように正確にスケジュールを設定することができ、それは非常に使いやすいです。

0

あなたのタイミングの問題はかなり処理されていますが(私は上記のほとんどに同意します)、私はWCFに関するいくつかの情報を提供することができます。 WCFサービスは、単にアプリケーションドメイン内でホストされます。このドメインは、Windowsフォーム、コンソールアプリケーション、ASP.net、この場合はWindowsサービスです。

そう意味では、あなたがWCFを経由してWindowsサービスを露出していない、あなたは、Windowsサービスアプリケーションドメイン内でWCFサービスをホスト以上です。 Windowsサービスに移行する前に、ウィンドウフォームにサービス(タイマーオブジェクトを含む)をテストすることをお勧めします。デバッグとテストが簡単です。 "DerivativesCalculatorService" 例えば

serviceType_MyEmailer = typeof(MyEmailerServiceType); 
    ServiceHost host_MyEmailer; 


    host_MyEmailer = new ServiceHost(serviceType_MyEmailer); 

ルックをオンライン:

は、Aは、WCFサービスは、実際には独自のスレッドで実行されているホストされています。コードでWCFサービスをホストする方法を説明します。

ここでのタイミングは、サービス自体の中にあります。すぐに初期化されるシングルトンクラスになるようにサービスクラスを作成し、その初期化時に(他の回答に見られるように)Timerオブジェクトを開始することができます。

このようにして、WCFサービスはクラスの永続インスタンスを持ち、タイマーオブジェクトは静かにオフになります。それらのすべてをWindowsサービスでホストして、完了してください。

これが役に立ちます。

関連する問題