Работает на службе Windows, которая должна обрабатывать запрос в каждый предопределенный промежуток времени. Thread.Sleep отлично работает, но проблема в том, что при вызове службы останавливается, замораживание службы, если поток находится в спящем режиме. Я читал об альтернативном подходе, таком как Timer, но проблема с этим заключается в том, что этот определенный интервал начинается с нового потока. Есть ли лучший способ добиться такого же результата и не запускаться.Альтернатива Thread.Sleep
ответ
Вместо этого вы можете использовать WaitHandle.WaitOne. Вы можете дождаться закрытия события для запуска или таймаута, который вы указываете в предопределенный интервал времени.
static AutoResetEvent seviceStopRequested = new AutoResetEvent(false);
....
((AutoResetEvent)stateInfo).WaitOne([timeout], false)
Затем, когда служба остановки вызывается, вы можете просто вызвать событие
seviceStopRequested .Set();
Используйте таймер, чтобы добавить команды/задачи, включая задачи для завершения работы в очередь блокировки. Сделайте свою службу поток ждать задач в очереди блокировки и выполнять их, когда они доступны. Поток таймера будет периодически добавлять задачи в очередь.
Что вы ищете - это способность реагировать на уведомление о двух разных событиях - (1), когда таймер истекает, и (2) когда служба остановлена. @Anurag Ranhjan находится на правильном пути с WaitHandle
, но у вас есть два события, а не один. Чтобы правильно справиться с этим, выполните следующие действия.
Сначала определите два события, которые вас волнуют, используя ManualResetEvent
. Вы можете использовать AutoResetEvent
, если хотите; Я просто предпочитаю перезагружать события вручную.
using System.Threading;
ManualResetEvent shutdownEvent = new ManualResetEvent();
ManualResetEvent elapsedEvent = new ManualResetEvent();
Вам необходимо активировать эти события, когда они происходят. Для shutdownEvent
это легко. В обратном вызове OnStop
вашей службы Windows просто установите это событие.
protected override void OnStop
{
shutdownEvent.Set();
}
Для elapsedEvent
, вы могли бы сделать это несколько различных способов. Вы можете создать фоновый поток, то есть ThreadPool
, который использует Thread.Sleep
. Когда поток просыпается, установите elapsedEvent
и вернитесь спать. Так как это фоновый поток, он не повредит ваш сервис, когда он отключится. Альтернатива, как вы уже сказали, заключается в использовании таймера. Вот как я это делаю.
using System.Timers;
Timer timer = new Timer();
timer.Interval = 5000; // in milliseconds
timer.Elapsed += delegate { elapsedEvent.Set(); };
timer.AutoReset = false; // again, I prefer manual control
timer.Start();
Теперь, когда у вас есть события, которые установлены правильно, поместите их в WaitHandle
массиве.
WaitHandle[] handles = new WaitHandle[]
{
shutdownEvent,
elapsedEvent
};
Вместо метода WaitHandle.WaitOne
, использовать метод WaitHandle.WaitAny
внутри цикла в то время, как это.
while (!shutdownEvent.WaitOne())
{
switch (WaitHandle.WaitAny(handles))
{
case 0: // The shutdownEvent was triggered!
break;
case 1: // The elapsedEvent was triggered!
Process(); // do your processing here
elapsedEvent.Reset(); // reset the event manually
timer.Start(); // restart the timer manually
break;
default:
throw new Exception("unexpected switch case");
}
}
Я сконструировал этот пример из производственного кода в своем проекте. Я знаю, что этот механизм работает, но я, возможно, пропустил что-то в записи. Дайте знать, если у вас появятся вопросы.
Пожалуйста, не рекомендуем 'System.Timers.Timer'. Он ест неискушенные исключения, что заставляет все работать, хотя это может и не быть. Измените пример, который вместо этого использует 'System.Threading.Timer'. – jgauffin
Для чего стоит большая часть блокирующих вызовов в .NET BCL будет отвечать на Thread.Interrupt
. То есть, они не будут ждать полного количества времени, указанного при вызове, и вместо этого возвращаются немедленно.Однако я бы избегал использовать этот метод и вместо этого использовал один ManualResetEvent
для выполнения как ожидания ожидания, так и сигнала останова. Это будет выглядеть так.
public class MyServer : ServiceBase
{
private ManualResetEvent shutdown = new ManualResetEvent(false);
protected override void OnStart(string[] args)
{
new Thread(
() =>
{
while (!shutdown.WaitOne(YourInterval))
{
// Do work here.
}
}).Start();
}
protected override void OnStop()
{
shutdown.Set();
}
}
Я обычно использую следующую закономерность:
public class MyJob
{
System.Threading.Timer _timer;
bool _isStopped;
public void MyJob()
{
_timer = new Timer(OnWork, null, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(-1));
}
private void OnWork(object state)
{
//[.. do the actual work here ..]
if (!_isStopped)
_timer.Change(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(-1));
}
public void Stop()
{
_isStopped = true;
_timer.Change(TimeSpan.FromSeconds(-1), TimeSpan.FromSeconds(-1));
}
public void Start()
{
_isStopped = false;
_timer.Change(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(-1));
}
}
Ключевые моменты:
- Только используя исходный интервал дает вам полный контроль, когда таймер запускается снова (т.е. работы время не подсчитывается в интервале таймера)
- Изменение таймера на -1 секунд приостанавливает его до изменения
Поэтому он должен работать со всеми вашими требованиями.
- 1. Альтернатива Thread.Sleep();
- 2. Альтернатива Thread.Sleep() перед сокетом
- 3. Альтернатива Thread.Sleep, что блок
- 4. Альтернатива Thread.Sleep в C#?
- 5. Точная альтернатива Thread.Sleep
- 6. Java - альтернатива thread.sleep
- 7. Альтернатива для Thread.sleep() в java
- 8. Альтернатива методу Thread.sleep в Android
- 9. Хорошая альтернатива для thread.sleep (для сеанса пользователей)
- 10. Есть ли альтернатива Thread.sleep в Java
- 11. Альтернатива для Thread.Sleep() временно приостановить программу
- 12. Thread.sleep зовущего Thread.sleep
- 13. Альтернатива Thread.Sleep в окнах Форма, отличная от Timer
- 14. Thread.Sleep (1); слишком медленно для анимации Silverlight, есть ли альтернатива?
- 15. Нет-замерзает альтернатива Thread.Sleep время ожидания внутри задачи
- 16. Thread.sleep внутри актеров Scala
- 17. Thread.Sleep() кражи отладчиков фокус
- 18. Thread.Sleep в Asp.net vNext
- 19. Использование Thread.Sleep при использовании программы
- 20. Альтернативы Thread.Sleep() для имитации пауз
- 21. Java Thread.sleep
- 22. Асинхронного Thread.Sleep()
- 23. Точнее Thread.Sleep
- 24. C# Thread.Sleep()
- 25. Thread.sleep() реализация
- 26. Thread.Sleep() замораживает
- 27. Thread.sleep() альтернативы
- 28. Thread.Sleep-реализация
- 29. Повторяет ли Thread.Sleep (200) и Thread.Sleep (1) то же самое?
- 30. Десять раз Thread.Sleep (100) или один Thread.Sleep (1000)?
Запустите новую тему и поставьте ее, чтобы спать, а не спать. Кажется, это проблема дизайна. –
Почему бы вам не пойти на таймер, который просыпается через равные промежутки времени? – GETah
Почему бы вам не использовать событие, чтобы сигнализировать о готовности нового запроса и ждать этого события. Спящие и таймеры являются решениями второй скорости. –