C # - альтернатива Thread.Sleep? - PullRequest
0 голосов
/ 27 марта 2011

Я делаю все это в C #, в Visual Studio 2008.

Я хочу замедлить работу моего алгоритма, чтобы пользователь мог наблюдать за его работой. В GUI видны периодические изменения, поэтому я добавляю «thread.sleep» после каждого экземпляра.

Проблема в том, что "thread.sleep", если он установлен как минимум секунду после нескольких экземпляров "thread.sleep" (после нескольких циклов), просто замораживает весь графический интерфейс и сохраняет его таким образом до завершения программы. Не сразу, но это всегда происходит. Как скоро зависит продолжительность сна.

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

Как решить эту проблему? Альтернатива алгоритму паузы в определенный момент?

Ответы [ 4 ]

6 голосов
/ 27 марта 2011

Прежде всего, не заставляйте пользователей ждать выполненную работу, прежде чем они даже подумают, когда она будет закончена. Это бессмысленно. Пожалуйста, просто скажите нет.

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

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

Опять же, пожалуйста, не делайте этого.

4 голосов
/ 27 марта 2011

Я предполагаю, что все заканчивается одним потоком.Пользователь, вероятно, вызывает этот алгоритм, нажимая кнопку или что-то подобное.Это обрабатывается очередью сообщений вашего основного потока.Пока этот обработчик не вернется, графический интерфейс вашего приложения не сможет обновиться.Необходимо, чтобы очередь сообщений перекачивалась на регулярной основе, чтобы оставаться отзывчивой.

Сон почти никогда не является хорошей идеей и определенно не очень хорошей идеей в потоке графического интерфейса.Я не буду рекомендовать, чтобы вы продолжали использовать sleep и чтобы ваш GUI реагировал, вызывая Application.DoEvents.

Вместо этого вы должны запустить этот алгоритм в фоновом потоке, а после его завершения он должен датьосновная нить.

3 голосов
/ 27 марта 2011

Вы собираетесь совершить несколько довольно распространенных блокировок пользовательского интерфейса:

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

Вместо этого:

  • Отображать результаты в гаджете, таком как ListBox, чтобы пользователь мог просматривать результаты в своем темпе
  • Поддерживать интерактивный интерфейс пользователя с помощью потоков
  • Замедляйте время для своей выгоды с помощью отладчика
0 голосов
/ 27 марта 2011

Это зависит от многих вещей, поэтому трудно дать конкретный ответ из того, что вы сказали. Тем не менее, вот некоторые вопросы, которые могут иметь отношение к делу:

Вы делаете это в потоке пользовательского интерфейса (например, в потоке кнопки формы или события пользовательского интерфейса, который инициировал начатую работу)? Если это так, может быть лучше создать новый поток для выполнения работы.

Почему ты вообще спишь? Если состояние, относящееся к текущей работе, доступно всем соответствующим потокам, может ли наблюдатель не просто наблюдать это без спящего рабочего потока? Возможно, рабочий поток мог бы записать индикатор текущего прогресса в энергозависимую или заблокированную переменную (он должен быть заблокирован, если он больше, чем размер указателя - например, int или объект - но не иначе. Если не заблокирован, то энергозависимость предотвратит кэш-память несоответствие между процессорами, хотя это может и не иметь большого значения). В этом случае у вас может быть таймер форм (в .Net существуют разные таймеры для разных целей), который проверяет состояние этой переменной и обновляет пользовательский интерфейс, чтобы отразить выполняемую работу, без необходимости что-либо делать рабочему потоку. В лучшем случае может оказаться полезным Yield() в рабочем потоке, но вряд ли это понадобится.

...