Использование ProgressBar в качестве панели ожидания - как избежать зависаний? - PullRequest
1 голос
/ 19 июля 2010

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

Я использую ProgressBar (System.Windows.Forms.ProgressBar в режиме выделения) как часть этого элемента управления.Мне не нужно обновлять состояние индикатора выполнения, я просто хочу, чтобы он двигался снова и снова, пока график не будет создан.

Прямо сейчас я использую его в следующей схеме:
- Запустить панель ожидания (ProgressBar появляется и запускается)
- Методы построения графика вызовов
- Когда график готов,строка ожидания будет скрыта.

Проблема в том, что некоторые методы построения графиков действительно требуют вычислений, и в такие моменты панель ожидания зависает.Как я могу избежать этих зависаний?Должен ли я использовать какой-нибудь рабочий / фоновый рабочий?И если да, то какой самый простой способ сделать это?

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

РЕДАКТИРОВАТЬ

ОК, как и предполагалось, я создал отдельный поток для этих сложных вычислений, чтобы избежать зависаний.

Но как дождаться окончания потока и не заморозить графический интерфейс?

Я пытался, как предлагалось здесь , что-то вроде этого:

Thread t = new Thread( () => { DoSomeLongAndDemandingTask(withParameters); });
t.Start();
t.Join()

// do something that needs to be done after thread finishes
InvokeMeAfterThreadFinished();

Но это зависает графический интерфейс.Есть ли другой способ избежать этих зависаний?

Ответы [ 2 ]

4 голосов
/ 19 июля 2010

Вы ответили на свой вопрос - обычно ответ состоит в том, чтобы переместить вычисление в фоновый поток.Существует компонент WinForms, называемый BackgroundWorker, который выполняет за вас большую работу:

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx http://dotnetperls.com/backgroundworker

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

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

1 голос
/ 19 июля 2010

Использование класса BackgroundWorker - это самый простой способ выполнения фоновых вычислений.

Однако, будьте осторожны, чтобы методы построения диаграмм, которые вы используете в фоновом режиме, не обновляли пользовательский интерфейс. Все обновления самого пользовательского интерфейса должны выполняться потоком пользовательского интерфейса. Таким образом, фоновый поток должен будет «маршалировать» такие вызовы пользовательского интерфейса - см. Control.Invoke для начальной точки на этом.

...