0

特定の間隔でメールボックスを読み取るために使用されるアプリケーションを作成しました。新しいメールがある場合は、添付ファイルをダウンロードして pdf ファイルを作成し、100 以上のメールを結合して特定のリストに送り返します。一部のサーバー ポリシーにより、ウィンドウ サービスに変換する立場にあります。以下のコードでタイマーを使用しました

private System.Threading.Timer timer;
timer = new System.Threading.Timer(TimerTick, null, TimeSpan.Zero, TimeSpan.FromMinutes(1));

void TimerTick(object state)
{
  var minute = DateTime.Now.Minute;
  if (minute != lastMinute && minute % 5 == 0)
  {
    //check mail here
  }
}

このようなタイマーの実装は効率的な方法ですか? これを処理するより良い方法はありますか?アプリケーションは 24 x7 で実行する必要があり、非効率な場合はより多くの CPU メモリを使用することになるため、パフォーマンスが心配です。

このシナリオで利用できる唯一の最適なオプションはタイマーですか?

4

4 に答える 4

4

サービスのパフォーマンスを監視する必要があります。パフォーマンスの問題が発生した場合:

  1. それを測定する
  2. コードを変更する
  3. もう一度測定する
  4. あなたの測定値を比較するよりも

System.Threading.Timerは、コールバックメソッドを使用し、スレッドプールスレッドによって提供されるシンプルで軽量なタイマーです。

  • System.Timers.Timerサーバーベースのタイマー機能を検討することもできます。

保守性とデバッグのヒント:

  • コードを変更せずに、XML構成ファイルを使用して間隔を設定します。これにより、ユーザーまたは管理者がサービスを制御できるようになります。

サービスを簡単にデバッグするためのコードを使用します。

static void Main()
{
#if (!DEBUG)
    System.ServiceProcess.ServiceBase[] ServicesToRun;
    ServicesToRun = new System.ServiceProcess.ServiceBase[] { new Service1() };
    System.ServiceProcess.ServiceBase.Run(ServicesToRun);
#else
    // Debug code: this allows the process to run as a non-service.
    // It will kick off the service start point, but never kill it.
    // Shut down the debugger to exit
    Service1 service = new Service1();
    service.EntryMethodHere(); // Your method that activates your timer
    // Put a breakpoint on the following line to always catch
    // your service when it has finished its work
    System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#endif 
}
于 2012-10-24T19:51:05.380 に答える
2

タイマーを 1 分間として 5 回ごとにメールをチェックするよりも、単純に 5 分間にする方が効率的です。

timer = new System.Threading.Timer(TimerTick, null, TimeSpan.Zero, TimeSpan.FromMinutes(5)); 
于 2012-10-24T19:35:12.003 に答える
2

タイマーは非常に効率的ですが、代わりに TimeSpan.FromMinutes(5) を使用して、TimerTick の非効率的な条件を削除する必要があります。TimerTick は ThreadPool スレッドで実行されるため、メール サーバーを再度確認する前に、前のイベントが終了していることを確認する必要があります。

private System.Threading.Timer timer = new System.Threading.Timer(TimerTick, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));

private bool FCheckingMails = false;
void TimerTick(object state)
{
    if (FCheckingMails) return;
    FCheckingMails = true;
    try
    {
        //check mail here
    }
    finally
    {
        FCheckingMails = false;
    }
}

FCheckingMails はスレッドセーフではないと言う人もいるかもしれませんが、実際にはその必要はありません。

効率が気になる場合は、1 時間に 12 回実行されるコードではなく、1 分間に数百万回実行されるコードを確認する必要があります。

あなたの探求を頑張ってください。

于 2012-10-24T20:15:13.740 に答える
0

System.Threading.Timer は、CPU とメモリの使用量の点で非常に軽量である必要があるため、問題はないと思います。より一般的には、この種のジョブは通常、週末、月の日付 (たとえば、毎月の最初または最後の日に処理を行う) などの情報を使用して、より詳細に構成できるスケジューラによってトリガーされます。

そのルートをたどる場合は、オープン ソースの .net cron ジョブ スケジューラであるQuartz.Netを調べてください。

于 2012-10-26T13:21:12.103 に答える