Как я могу выполнить короткую задержку на С# без использования сна?
Я невероятно новичок в программировании, и я до сих пор учился достаточно хорошо, но я все еще не могу понять, как сделать задержку так, как я хочу. То, над чем я работаю, - это своего рода тестовая "игра", использующая приложение форм Windows, которое включает в себя боевую систему. В нем я хочу сделать NPC, который выполняет действие каждые пару секунд. Проблема в том, что я также хочу позволить игроку взаимодействовать между атаками. Thread.sleep действительно не работает для меня не только потому, что я не знаю, как многопоточно, но всякий раз, когда я пытаюсь запустить его, скажем, вот так:
textBox1.Text += "\r\nThread Sleeps!";
System.Threading.Thread.Sleep(4000);
textBox1.Text += "\r\nThread awakens!";
Кажется, он настаивает на том, чтобы спать первым, а затем печатать обе строки.
Я думаю, что все, что я могу сказать в данный момент, но если это еще слишком расплывчато или многословно, не стесняйтесь говорить мне.
Короче говоря, In С# я хочу сделать что-то задержка перед запуском, но в то же время разрешить взаимодействие с пользователем.
Ответы
Ответ 1
Если вы используете .NET 4.5, вы можете использовать новую структуру async/await для сна, не блокируя поток.
Как это работает, вы отмечаете функцию, которая нуждается в асинхронных операциях, с ключевым словом async
. Это всего лишь намек на компилятор. Затем вы используете ключевое слово await
в строке, где вы хотите, чтобы ваш код выполнялся асинхронно, и ваша программа будет ждать, не блокируя нить или пользовательский интерфейс. Метод, который вы вызываете (в строке ожидания), должен быть помечен также ключевым словом async
и обычно называется именем, заканчивающимся на Async, как в ImportFilesAsync.
Что вам нужно сделать в вашем примере:
- Убедитесь, что ваша программа имеет .Net Framework 4.5 как Target Framework
- Отметьте свою функцию, которая должна спать с ключевым словом
async
(см. пример ниже)
- Добавьте
using System.Threading.Tasks;
в свой код.
Теперь ваш код готов использовать метод Task.Delay
вместо метода System.Threading.Thread.Sleep
(можно использовать await
на Task.Delay
, потому что Task.Delay
помечен async
в его определении).
private async void button1_Click(object sender, EventArgs e)
{
textBox1.Text += "\r\nThread Sleeps!";
await Task.Delay(3000);
textBox1.Text += "\r\nThread awakens!";
}
Здесь вы можете узнать больше о Task.Delay и Await.
Ответ 2
Извините за пробуждение старого вопроса вроде этого.
Но я думаю, что первоначальный автор хотел в качестве ответа:
Вам нужно заставить свою программу сделать графическое обновление после внесения изменений в текстовое поле1. Вы можете сделать это, вызвав Update();
textBox1.Text += "\r\nThread Sleeps!";
textBox1.Update();
System.Threading.Thread.Sleep(4000);
textBox1.Text += "\r\nThread awakens!";
textBox1.Update();
Обычно это будет выполняться автоматически, когда поток будет выполнен.
Ex, вы нажимаете кнопку, изменения вносятся в текст, нити умирают, а затем .Update()
запускается, и вы видите изменения.
(Я не эксперт, поэтому я не могу сказать вам, когда его уволили, но что-то подобное в любом случае.)
В этом случае вы делаете изменения, приостанавливаете поток, а затем снова меняете текст, и когда поток наконец умирает, загорается .Update()
. Это приводит к тому, что вы видите только последнее изменение, внесенное в текст.
У вас возникла бы такая же проблема, если бы у вас было длинное выполнение между текстовыми изменениями.
Ответ 3
Возможно, вы можете использовать таймеры: http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx
Таймеры могут обеспечить точность до 1 миллисекунды. В зависимости от интервала тика будет генерироваться событие. Сделайте свой материал внутри события тика.
Ответ 4
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();
}
}
Ответ 5
Добавив using System.Timers;
в свою программу, вы можете использовать эту функцию:
private static void delay(int Time_delay)
{
int i=0;
// ameTir = new System.Timers.Timer();
_delayTimer = new System.Timers.Timer();
_delayTimer.Interval = Time_delay;
_delayTimer.AutoReset = false; //so that it only calls the method once
_delayTimer.Elapsed += (s, args) => i = 1;
_delayTimer.Start();
while (i == 0) { };
}
Задержка - это функция и может использоваться как:
delay(5000);