C # спит в течение 500 миллисекунд - PullRequest
7 голосов
/ 28 марта 2010

Не могли бы вы сказать, как мне приостановить свою программу на 500 миллисекунд, а затем продолжить?

Я прочитал Thread.Sleep(500) не хорошо, так как он поддерживает поток GUI.

Используя таймер, он запускает обратный вызов ...

Я просто хочу подождать 500 мс, а затем перейти к следующему утверждению.

Пожалуйста, сообщите.

РЕДАКТИРОВАТЬ: мне нужно отобразить сообщение в строке состояния в течение 500 мс, а затем обновить сообщение с другим. Извините, я имел в виду 500, а не 50.

РЕДАКТИРОВАТЬ: Я понимаю, что все, что вы сказали. но: [Я просто хочу подождать 500 мс и затем перейти к следующему утверждению.] Я думаю, потому что это такой короткий интервал, я собираюсь сделать Thread.Sleep (500) в главном потоке GUI. В противном случае мне пришлось бы переписать много кода, чтобы вместить этот короткий интервал в 500 миллисекунд.

РЕДАКТИРОВАТЬ: я попытаюсь переформатировать мое сообщение о состоянии, чтобы пауза не нужна.

Ответы [ 6 ]

5 голосов
/ 28 марта 2010

Хм, то, что вы пытаетесь сделать, совершенно несовместимо с моделью программирования Windows. Нативная программа для Windows управляется событиями. Ваша программа всегда бездействует, находясь в цикле, запущенном Application.Run (), ожидая, пока Windows сообщит ей, что произошло что-то интересное, на что она должна ответить. Запросы на рисование, щелчки мышью, истечение таймера и тому подобное.

Ваша программа должна ответить на это и отфильтровать то, что вам интересно. Когда вы опускаете кнопку в форме, вы всегда интересуетесь событием Click, которое генерируется, когда Windows отправляет уведомление MouseDown. Ваш обработчик события Click запускает какой-то пользовательский код, который вы пишете. Как обновить сообщение в строке состояния в вашем случае.

Обновление сообщения в строке состояния через полсекунды не имеет смысла. Что именно произошло за те 500 миллисекунд, которые изменили реакцию вашей программы на события? Вы можете вызвать метод Update () в StatusBar, чтобы увидеть новое сообщение, а затем вызвать System.Threading.Thread.Sleep (500), чтобы получить то, что вы хотите. Вам это сойдет с рук, призрак «Не отвечает», который выдает Windows, в течение нескольких секунд останавливает вашу программу.

Но это не имеет большого смысла, ничего не происходило в течение этой полсекунды, состояние вашей программы не изменилось. Он не мог измениться, он был мертв для Windows и не получал никаких сообщений, которые позволили бы ему изменить состояние.

Ну, это все, что я могу сделать. Пожалуйста, обновите ваш вопрос и объясните, почему вам нужно это сделать. На всякий случай: если вы обдумываете это, чтобы подделать что-то важное за полсекунды, ваш пользователь не будет впечатлен. В конце концов она заметит, что ваш пользовательский интерфейс мертв на полсекунды, и ничего не будет видно.

5 голосов
/ 28 марта 2010

У вас есть два варианта:

  • Используйте таймер, как вы предложили. Разделите ваш метод на два метода, foo1 и foo2. Используйте foo1 для запуска таймера и запуска foo2 в обратном вызове.
  • Используйте BackgroundWorker для запуска всей функции и используйте Thread.Sleep в рабочем потоке.

Из вашего обновления кажется, что вам нужно всего лишь изменить одно поле. Я определенно рекомендую первый способ: использование таймера. Запуск BackgroundWorker для этой задачи является излишним и просто даст вам ненужную дополнительную работу и сложности.

4 голосов
/ 28 марта 2010

Вместо того, чтобы приостанавливать пользовательский интерфейс напрямую на 500 мс, вы всегда можете использовать BackgroundWorker . Это приведет к тому, что ваш обратный вызов будет выполняться в отдельном потоке, где вы можете использовать Thread.Sleep, чтобы приостановить его, не блокируя пользовательский интерфейс. Затем, когда вы закончите, просто обновите строку состояния новым сообщением.

2 голосов
/ 28 марта 2010

В C # лучше всего использовать таймер и запустить обратный вызов.

В F # есть отличный способ сделать то, что вы хотите, см.

F # асинхронный на стороне клиента

, который показывает, как написать прямой код и чтобы язык позаботился о обратных вызовах для вас.

2 голосов
/ 28 марта 2010

Было бы полезно больше контекста вопроса.

Thread.Sleep(50) приостановит текущий поток на 50 миллисекунд. Если вы делаете это в потоке пользовательского интерфейса, то да, он заморозит пользовательский интерфейс на 50 миллисекунд. Однако, если вы используете другой поток для этой обработки, то вызов Sleep в этом потоке приостановит его на 50 миллисекунд без замораживания вашего потока пользовательского интерфейса.

См. Ответ Марка на этот вопрос для примера использования BackgroundWorker экземпляра для выполнения того, что вам нужно.

0 голосов
/ 28 марта 2010

Вам нужно выделить другой поток. В этой теме вы Sleep(500) и измените необходимые данные. Внимание: вам нужно будет использовать диспетчер исходного потока, потому что данные, связанные с пользовательским интерфейсом, обычно должны обновляться из потока графического интерфейса.

...