14

毎正時にメソッドを実行したい。いくつかのコードを書きましたが、私の目的には十分ではありません。以下のコードは 60 分ごとに動作しています。

public void Start()
{
    System.Threading.Timer timerTemaUserBilgileri = new System.Threading.Timer(new System.Threading.TimerCallback(RunTakip), null, tmrTemaUserBilgileri, 0);
}

public void RunTakip(object temauserID)
{
    try 
    {
        string objID = "6143566557387";
        EssentialMethod(objID);
        TimeSpan span = DateTime.Now.Subtract(lastRunTime);
        if (span.Minutes > 60)
        {
            tmrTemaUserBilgileri = 1 * 1000;
            timerTemaUserBilgileri.Change(tmrTemaUserBilgileri, 0);
        }
        else
        {
            tmrTemaUserBilgileri = (60 - span.Minutes) * 60 * 1000;
            timerTemaUserBilgileri.Change(tmrTemaUserBilgileri, 0);
        }
        watch.Stop();
        var elapsedMs = watch.ElapsedMilliseconds;
    }
    catch (Exception ex)
    {
        timerTemaUserBilgileri.Change(30 * 60 * 1000, 0);
        Utils.LogYaz(ex.Message.ToString());
    }
}

public void EssentialMethod(objec obj)
{
    //some code
    lastRunTime = DateTime.Now;
    //send lastruntime to sql 
}
4

8 に答える 8

8

クローンジョブが最初の選択肢であるべきだというセニョール・ソルトに同意します。ただし、OP は c# から正時に毎時要求しました。そのために、最初の時限イベントを正時に起動するように設定しました。

int MilliSecondsLeftTilTheHour()
{
    int interval;

    int minutesRemaining = 59 - DateTime.Now.Minute;
    int secondsRemaining = 59 - DateTime.Now.Second;
    interval = ((minutesRemaining * 60) + secondsRemaining) * 1000;

    // If we happen to be exactly on the hour...
    if (interval == 0)
    {
        interval = 60 * 60 * 1000;
    }
    return interval;
}

Timer timer = new Timer();
timer.Tick += timer_Tick;
timer.Enabled = true;
timer.Interval = MilliSecondsLeftTilTheHour();

ここでの問題は、上記の timer.Interval がたまたま 45 分 32 秒の場合、タイマーは初回だけでなく 45:32 ごとに起動し続けることです。したがって、timer_Tick メソッド内で、timer.Interval を 1 時間に再調整する必要があります。

 void timer_Tick(object sender, EventArgs e)
 {
     // The Interval could be hard wired here to  60 * 60 * 1000 but on clock 
     // resets and if the job ever goes longer than an hour, why not
     // recalculate once an hour to get back on track.
     timer.Interval = MilliSecondsLeftTilTheHour();
     DoYourThing();
 }
于 2014-12-08T18:25:04.880 に答える
5

/Anarion のソリューションに基づいた小さなコメントで、コメントに収まりませんでした。

短い間隔でタイマーを作成できます(必要な精度に応じて、1秒としましょう)

正確に行う必要はまったくありません。「この時間が発射したい時間であることを確認するにはどうすればよいか」を考えているだけです。別の方法として、「次の 1 時間が発射したい時間であることを確認するにはどうすればよいか」と考えることもできます。そのように考えたら、精度がまったく必要ないことに気付いたら、1 時間に 1 回ティックして、スレッドを設定します。次の時間。1 時間に 1 回チェックすると、次の 1 時間前のある時点にいることがわかります。

Dim dueTime As New DateTime(Date.Today.Year, Date.Today.Month, Date.Today.Day, DateTime.Now.Hour + 1, 0, 0)
Dim timeRemaining As TimeSpan = dueTime.Subtract(DateTime.Now)

t = New System.Threading.Timer(New System.Threading.TimerCallback(AddressOf Method), Nothing, CType(timeRemaining.TotalMilliseconds, Integer), System.Threading.Timeout.Infinite)
于 2014-03-05T16:10:05.707 に答える
1

サーバーでCronジョブを使用して、指定された間隔で関数を呼び出します

リンクはこちら http://www.thesitewizard.com/general/set-cron-job.shtml

于 2013-10-10T09:26:29.303 に答える
0

以下のコードを試してみてください。ループはリソースを節約するために決定され、正確な時間ごとに実行されます。つまり、分と秒の両方で (そしてほぼゼロに等しいミリ秒:

using System;
using System.Threading.Tasks;

namespace COREserver{
    public static partial class COREtasks{   // partial to be able to split the same class in multiple files
        public static async void RunHourlyTasks(params Action[] tasks)
        {
            DateTime runHour = DateTime.Now.AddHours(1.0);
            TimeSpan ts = new TimeSpan(runHour.Hour, 0, 0);
            runHour = runHour.Date + ts;


            Console.WriteLine("next run will be at: {0} and current hour is: {1}", runHour, DateTime.Now);
            while (true)
            {
                TimeSpan duration = runHour.Subtract(DateTime.Now);
                if(duration.TotalMilliseconds <= 0.0)
                { 
                    Parallel.Invoke(tasks);
                    Console.WriteLine("It is the run time as shown before to be: {0} confirmed with system time, that is: {1}", runHour, DateTime.Now);
                    runHour = DateTime.Now.AddHours(1.0);
                    Console.WriteLine("next run will be at: {0} and current hour is: {1}", runHour, DateTime.Now);
                    continue;
                }
                int delay = (int)(duration.TotalMilliseconds / 2);
                await Task.Delay(30000);  // 30 seconds
            }
        }
    }
}
于 2017-01-17T08:24:52.530 に答える