0

最近、vb.net から C# に移行しましたが、作成した Windows サービスを開始する際に問題が発生しています。app.config ファイルから一度に読み取られるサービスを毎日実行したいと考えています。vb.net では、Timer を使用してメソッドを呼び出しました。

Private WithEvents Alarm As Timer = New Timer(30000)
Public Sub OnTimedEvent(ByVal source As Object, ByVal e As ElapsedEventArgs) Handles Alarm.Elapsed

私がこれまでに持っているC#コードは次のとおりです。

namespace MyWindowsService
{
class Program : ServiceBase
{
  Timer alarm = new Timer(30000);
  public string str_dbserver;
  public string str_year;
  public string str_time;
  public string str_dbConnection;
  bool service_running;

static void Main(string[] args)
{
    ServiceBase.Run(new Program());
}

public Program()
{
  this.ServiceName = "MyWindowsService";
}


public void OnTimedEvent(object source, ElapsedEventArgs e)
{      
    service_running = false;

    //declare variables and get info from config file
    DateTime dtNow;
    dtNow = DateTime.Now;
    System.Configuration.AppSettingsReader configurationAppSettings = new System.Configuration.AppSettingsReader();
    str_dbserver = Convert.ToString(configurationAppSettings.GetValue("dbServer", typeof(System.String)));
    str_year = Convert.ToString(configurationAppSettings.GetValue("sYear", typeof(System.String)));
    str_time = Convert.ToString(configurationAppSettings.GetValue("stime", typeof(System.String)));

    //split time from config to get hour, minute, second
    string[] str_atime = str_time.Split(new string[] { ":" }, StringSplitOptions.None);

    //check that service is not currently running and time matches config file
    if (DateTime.Now.Hour == Convert.ToInt32(str_atime[0]) && DateTime.Now.Minute == Convert.ToInt32(str_atime[1]) && service_running == false)
    {
        //service now running so write to log and send email notification
        service_running = true;

        try
        {
            //call functions containing service code here
            Function1();
            Function2();
        }
        catch (Exception ex)
        {

        } //end try/catch

        //service now finished, sleep for 60 seconds
        service_running = false;
    } //end if 
} //end OnTimedEvent

30 秒ごとに OnTimedEvent を呼び出して、構成ファイルから時間を確認し、コードを実行するコードが必要です。どんな助けでも大歓迎

4

3 に答える 3

1

タイマーをダンプし、スレッドを開始し、Sleep(30000) ループを使用します。

編集:さらに良いことに、RTC 値を取得し、次の実行時までに残っているミリ秒を計算します。2 で割り、その間隔で Sleep() を実行します。間隔が 100 ミリ秒未満になるまでこれを続けてから、Sleep() 関数をさらに 1000 実行します (RTC 時刻が現在の RTC 時刻よりも後であることを確認するため)構成ファイル)、およびループ ラウンド。

于 2012-09-20T10:17:53.353 に答える
1

なぜあなたは時間をポーリングしているのですか?30 秒ごとにポーリングしているにもかかわらず、深刻な負荷/ThreadPool 枯渇下では、タイマーが必要な分のスロットで起動しない可能性があります (ほとんどありませんが)。

期限までの TimeSpan を把握し、その時刻にタイマーが起動するように設定してみませんか?

使用しているタイマーは明確ではありませんが、Windows サービスには System.Threading.Timer 以外は使用しません。

于 2012-09-20T10:20:52.380 に答える
0

私を正しい方向に向けてくれた「Oded」と「Martin James」に感謝します。私のソリューションに欠けていたのはこれでした。タイマーが経過したことを認識できるように、次のコードをコンストラクター クラスに追加する必要がありました。

//call onTimedEvent when timer reaches 60 seconds
alarm.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 60 second.
alarm.Interval = 60000;

次に、次を使用してkernel32 dllをインポートしました。

using System.Runtime.InteropServices;

//import kernel32 so application can use sleep method
  [DllImport("kernel32.dll")]
  static extern void Sleep(uint dwMilliseconds);

この dll をインポートすることで、コードの実行が終了したら Sleep(60000) を使用できます。みんな助けてくれてありがとう

于 2012-09-20T10:44:13.917 に答える