С#: как начать поток в определенное время
Как начать фоновый поток в определенное время суток, скажем, 16:00?
Итак, когда приложения запустится, поток будет ждать до этого времени. Но если приложение запускается после этого времени, поток будет работать сразу.
ThreadPool.QueueUserWorkItem(MethodtoRunAt1600);
Ответы
Ответ 1
Вы можете настроить таймер на 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
}
Затем настройте его, используя
SetUpTimer(new TimeSpan(16, 00, 00));
Изменить: сохранить ссылку на таймер, поскольку он предназначен для сбора мусора независимо от того, включен ли таймер.
Ответ 2
Я бы использовал библиотеку планирования заданий, например Quartz, или просто создаю консольное приложение и запускаю его с помощью планировщика задач Windows в определенное время день.
Почему бы просто не использовать System.Timers.Timer?
- Таймеры не имеют механизма сохранения.
- Таймеры имеют негибкое планирование (только для установки времени начала и повтора, ничего не зависит от дат, времени суток и т.д.
- Таймеры не используют пул потоков (один поток за таймер)
- Таймеры не имеют реальных схем управления - вам придется написать свой собственный механизм для запоминания, организации и поиска ваших задач по имени, e
Ответ 3
Любое решение, зависящее от System.Timers.Timer
, System.Threading.Timer
или любого другого таймера, которое в настоящее время существует в .NET Framework, не будет выполнено с учетом изменений времени перехода на летнее время. Если вы используете какой-либо из этих таймеров, вам нужно будет сделать несколько опросов.
Windows имеет Ожидаемый таймер, который вы можете использовать, но не поддерживается никаким классом Framework. Несколько лет назад я написал обертку. Опубликованная статья больше не доступна, но вы можете загрузить полный исходный код из http://www.mischel.com/pubs/waitabletimer.zip
Тем не менее, если единственное, что делает ваша программа, запускается один раз в день, или если выполняемая задача может быть отколота от остальной части программы, вам почти наверняка будет лучше с запланированной задачей. И хотя я никогда не использовал Quartz.NET, у меня нет проблем с рекомендацией, основанной на хороших отзывах, которые я видел от людей, чье решение я доверяю.
Ответ 4
вы можете сделать это с помощью таймера:
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;
}
}
Ответ 5
Если вы ищете что-то "быстрое и грязное"... тогда вы можете просто начать свой поток в пуле потоков и "подождать" в нужное время.
// By the way, this code would be *INSIDE* of the background thread. That what
// the sentence above says, but apparently we devs only read code :)
while (DateTime.Now.TimeOfDay < myDesiredStartTime)
{
Thread.Sleep(1000);
}
Ответ 6
Вот простой способ запланировать метод, который будет вызываться один раз, либо сразу, либо в 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);
}
Ответ 7
Можем ли мы так использовать?
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
}
}
Ответ 8
Очень простое решение:
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()
}
Ответ 9
1- Вызов приложения из другого процесса
System.Diagnostics.Process.Start("CMD MyApplication.exe", "/C TIME 16:00");
2- Используйте Timer
и каждую минуту проверяйте текущее время.
3- Обработать событие изменения времени Windows в вашем приложении и каждый раз также проверять текущее время больше информации:
http://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.timechanged%28v=vs.100%29.aspx
Я надеюсь, что один из thoese поможет вам.
Ответ 10
Это то, что я использовал для достижения такой функциональности.
http://www.codeproject.com/Articles/12117/Simulate-a-Windows-Service-using-ASP-NET-to-run-sc