C#:如何在特定时间启动线程

Bob*_*Bob 33 .net c# multithreading

如何在一天中的特定时间(例如16:00)启动后台线程?

因此,当应用程序启动时,线程将一直等到那个时间.但如果应用程序在该时间之后启动,那么该线程将立即运行

ThreadPool.QueueUserWorkItem(MethodtoRunAt1600);

Sri*_*vel 57

你可以设置一个计时器16:00.我在这里回答了类似的问题.这应该对你有所帮助.

private System.Threading.Timer timer;
private void SetUpTimer(TimeSpan alertTime)
{
     DateTime current = DateTime.Now;
     TimeSpan timeToGo = alertTime - current.TimeOfDay;
     if (timeToGo < TimeSpan.Zero)
     {
        return;//time already passed
     }
     this.timer = new System.Threading.Timer(x =>
     {
         this.SomeMethodRunsAt1600();
     }, null, timeToGo, Timeout.InfiniteTimeSpan);
}

private void SomeMethodRunsAt1600()
{
    //this runs at 16:00:00
}
Run Code Online (Sandbox Code Playgroud)

然后使用它进行设置

SetUpTimer(new TimeSpan(16, 00, 00));
Run Code Online (Sandbox Code Playgroud)

编辑:保留定时器的引用,因为无论Timer是否处于活动状态,它都会被垃圾回收.

  • 你的片段让[程序员陷入困境](http://stackoverflow.com/questions/32356795/timer-class-not-firing-before-end-of-program). (14认同)
  • @Hans感谢您的评论.我已更新帖子以保留Timer的引用. (5认同)

Dam*_*ith 10

我会像Quartz一样使用Job Scheduling Library,或者只是创建控制台应用程序,并在一天中的特定时间使用Windows任务调度程序运行它.

为什么不直接使用System.Timers.Timer?

  • 定时器没有持久性机制.
  • 定时器具有不灵活的调度(仅能够设置开始时间和重复间隔,没有基于日期,时间等的任何内容.
  • 定时器不使用线程池(每个定时器一个线程)
  • 计时器没有真正的管理方案 - 您必须编写自己的机制,以便能够按名称记住,组织和检索您的任务,e

  • 为什么要安装一个完整的库来处理"Timer"这个微不足道的事情? (5认同)
  • @jgauffin:假设所需时间为0400。在1600处,您将计时器设置为12小时。在0200,计时器还有2个小时的时间。但这是“ Fall Back”的日子,时钟被调回一小时。因此现在是0100,计时器将在0300触发。“春季提前”这一天也发生了类似的事情。由于时钟提前,因此计时器将在0500触发。关键是系统时间*正确*。错误是假设12个小时的实时时间始终是12个小时的时钟时间。 (2认同)
  • @jgauffin:您不能在特定时间设置`System.Timers.Timer`或任何其他.NET计时器.您只能在一段时间内设置它们. (2认同)
  • @Damith:关于不使用线程池的计时器的观点不正确.除非正在执行其回调函数,否则计时器不占用线程,然后它在池线程上执行.如果您创建了100个计时器,那就不会分配100个线程. (2认同)

jga*_*fin 7

你可以用计时器做到这一点:

public class OncePerDayTimer : IDisposable
{
    private DateTime _lastRunDate;
    private TimeSpan _time;
    private Timer _timer;
    private Action _callback;

    public OncePerDayTimer(TimeSpan time, Action callback)
    {
        _time = time;
        _timer = new Timer(CheckTime, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
        _callback = callback;
    }

    private void CheckTime(object state)
    {
        if (_lastRunDate == DateTime.Today)
            return;

        if (DateTime.Now.TimeOfDay < _time)
            return;

        _lastRunDate = DateTime.Today;
        _callback();
    }

    public void Dispose()
    {
        if (_timer == null)
            return;

        _timer.Dispose();
        _timer = null;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @jgauffin 这是每秒轮询一次吗?对于每天运行一次的进程来说有点矫枉过正。 (3认同)
  • @JMG:你有这么少的CPU周期吗? (3认同)

Jim*_*hel 6

依赖于任何解决方案System.Timers.Timer,System.Threading.Timer或任何当前存在于.NET Framework中的其他定时器将在夏令时更改的脸失败.如果您使用任何这些计时器,您将不得不进行一些轮询.

Windows有一个可以使用的Waitable Timer,但任何Framework类都不支持它.几年前我为它写了一个包装器.我发布的文章已不再可用,但您可以从http://www.mischel.com/pubs/waitabletimer.zip下载完整的源代码.

也就是说,如果你的程序所做的唯一事情是每天运行一次,或者如果它执行的任务可以从程序的其余部分中分离出来,那么你几乎肯定会更好地完成计划任务.虽然我还没有使用Quartz.NET,但根据我从那些我信任的判断中看到的好评,我毫无疑问推荐它.