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

时间:2013-09-04 10:20:51

标签: c# .net multithreading

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

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

ThreadPool.QueueUserWorkItem(MethodtoRunAt1600);

10 个答案:

答案 0 :(得分:54)

您可以在16:00设置计时器。我已经回答了类似的问题here。 这应该对你有所帮助。

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
}

然后使用

进行设置
SetUpTimer(new TimeSpan(16, 00, 00));

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

答案 1 :(得分:11)

我会使用Quartz之类的作业调度库,或者只是创建控制台应用程序,并在当天的特定时间使用Windows任务调度程序运行它。

Why not just use System.Timers.Timer?

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

答案 2 :(得分:6)

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

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;
    }
}

答案 3 :(得分:6)

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

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

下载完整的源代码

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

答案 4 :(得分:1)

如果您正在寻找“快速而肮脏”的东西......那么您可以在线程池中启动您的线程,并在正确的时间“等待”。

// By the way, this code would be *INSIDE* of the background thread. That's what
// the sentence above says, but apparently we devs only read code :)
while (DateTime.Now.TimeOfDay < myDesiredStartTime)
{
    Thread.Sleep(1000);
}

答案 5 :(得分:1)

这是一种简单的方法,可以立即或在16:00安排一次方法调用。

var runAt = DateTime.Today + TimeSpan.FromHours(16);
if(runAt < DateTime.Now)
{
    MethodtoRunAt1600();    
}
else
{
    var dueTime = runAt - DateTime.Now;
    var timer = new System.Threading.Timer(_ => MethodtoRunAt1600(), null, dueTime, TimeSpan.Zero); 
} 

答案 6 :(得分:0)

我们可以这样使用吗?

DispatcherTimer timer ;
// When application is started
if (DateTime.Now.Hour == 16)
{
   // Start your task
}
else
{
    timer = new DispatcherTimer();
    timer.Interval = new TimeSpan(0, 1, 0);
    timer.Tick += timer_Tick;
    timer.Start();
}

然后检查每一分钟..

void timer_Tick(object sender, EventArgs e)
{
    if (DateTime.Now.Hour == 16)
    {
        // Start your task
    }
}

答案 7 :(得分:0)

一个非常简单的解决方案:

if (DateTime.Now.Hour > 16)
{
    MethodtoRunAt1600();
}
else
{
    var next16 = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 16, 0, 0);
    var timer = new Timer(MethodtoRunAt1600, null, next16 - DateTime.Now, TimeSpan.FromHours(24));
    timer.Start()
}

答案 8 :(得分:0)

1-从其他流程调用您的应用程序

System.Diagnostics.Process.Start("CMD MyApplication.exe", "/C TIME 16:00");

2-使用Timer,每1分钟检查一次当前时间。

3-处理您的应用程序中的Windows时间更改事件,每次还检查当前时间更多信息:

http://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.timechanged%28v=vs.100%29.aspx

我希望其中一个人会帮助你。

答案 9 :(得分:0)