Подождите несколько секунд, не блокируя выполнение пользовательского интерфейса.
Я хотел бы подождать несколько секунд между двумя инструкциями, но БЕЗ блокировки выполнения.
Например, Thread.Sleep(2000)
это плохо, потому что он блокирует выполнение.
Идея заключается в том, что я вызываю метод, а затем я жду X секунд (например, 20) при прослушивании события. В конце 20 секунд я должен выполнить некоторую операцию в зависимости от того, что произошло за 20 секунд.
Ответы
Ответ 1
Я думаю, что вы находитесь за Task.Delay. Это не блокирует поток, как Sleep, и это означает, что вы можете сделать это, используя один поток, используя модель программирования async.
async Task PutTaskDelay()
{
await Task.Delay(5000);
}
private async void btnTaskDelay_Click(object sender, EventArgs e)
{
await PutTaskDelay();
MessageBox.Show("I am back");
}
Ответ 2
Я использую:
private void WaitNSeconds(int segundos)
{
if (segundos < 1) return;
DateTime _desired = DateTime.Now.AddSeconds(segundos);
while (DateTime.Now < _desired) {
System.Windows.Forms.Application.DoEvents();
}
}
Ответ 3
Это хороший пример для использования другого потока:
// Call some method
this.Method();
Task.Factory.StartNew(() =>
{
Thread.Sleep(20000);
// Do things here.
// NOTE: You may need to invoke this to your main thread depending on what you're doing
});
Приведенный выше код ожидает .NET 4.0 или выше, в противном случае попробуйте:
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
Thread.Sleep(20000);
// Do things here
}));
Ответ 4
Решение Omar достойно *, если вы не можете обновить свою среду до .NET 4.5, чтобы получить доступ к API-интерфейсу async и ждать. Тем не менее, здесь есть одно важное изменение, которое должно быть сделано для того, чтобы избежать низкой производительности. Небольшая задержка должна быть добавлена между вызовами Application.DoEvents(), чтобы предотвратить чрезмерное использование ЦП. Добавив
Thread.Sleep(1);
перед вызовом Application.DoEvents() вы можете добавить такую задержку (1 миллисекунду) и запретить приложению использовать все доступные для него циклы процессора.
private void WaitNSeconds(int seconds)
{
if (seconds < 1) return;
DateTime _desired = DateTime.Now.AddSeconds(seconds);
while (DateTime.Now < _desired) {
Thread.Sleep(1);
System.Windows.Forms.Application.DoEvents();
}
}
* См. https://blog.codinghorror.com/is-doevents-evil/ для более подробного обсуждения возможных ловушек использования Application.DoEvents().
Ответ 5
Если вы не хотите блокировать вещи, а также не хотите использовать многопоточность, вот решение для вас:
https://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.110).aspx
Пользовательский интерфейс не блокируется, и таймер ждет 2 секунды, прежде чем что-то делать.
Вот код, следующий по ссылке:
// Create a timer with a two second interval.
aTimer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program... ");
Console.ReadLine();
Console.WriteLine("Terminating the application...");
Ответ 6
Я действительно вам не рекомендую использовать Thread.Sleep(2000)
из-за нескольких причин (некоторые из них описаны здесь), но больше всего потому, что это не полезно, когда оно приходит к отладке/тестированию.
Я рекомендую использовать С# Timer вместо Thread.Sleep()
. Таймеры позволяют часто выполнять методы (при необходимости) И очень легко использовать при тестировании! Там очень хороший пример того, как использовать таймер прямо за гиперссылкой - просто поместите свою логику "что произойдет через 2 секунды" прямо в метод Timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
.
Ответ 7
Посмотрите на класс System.Threading.Timer
. Я думаю, это то, что вы ищете.
Пример кода в MSDN, похоже, показывает, что этот класс очень похож на то, что вы пытаетесь сделать (проверьте статус через определенное время).