Как я Уступаю потоку UI для обновления UI при выполнении пакетной обработки в приложении WinForm?

Это может быть связано с выравниванием и заполнением байт, чтобы структура выходила на четное количество байтов (или слов) на вашей платформе. Например, в C на Linux следующие 3 структуры:

#include "stdio.h"


struct oneInt {
  int x;
};

struct twoInts {
  int x;
  int y;
};

struct someBits {
  int x:2;
  int y:6;
};


int main (int argc, char** argv) {
  printf("oneInt=%zu\n",sizeof(struct oneInt));
  printf("twoInts=%zu\n",sizeof(struct twoInts));
  printf("someBits=%zu\n",sizeof(struct someBits));
  return 0;
}

У членов, размер которых (в байтах) равен 4 байтам (32 бита), 8 байтам (2x 32 бита) и 1 байт (2 +6 бит) соответственно. Вышеупомянутая программа (в Linux с использованием gcc) печатает размеры 4, 8 и 4, где последняя структура дополняется так, что это одно слово (4 x 8 бит байтов на моей 32-битной платформе).

oneInt=4
twoInts=8
someBits=4
9
задан Guy 19 September 2008 в 22:06
поделиться

9 ответов

BackgroundWorker походит на объект, который Вы хотите.

14
ответ дан 4 December 2019 в 07:36
поделиться

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

Для отображения обновлений индикаторы выполнения или текст строки состояния являются двумя из наиболее распространенных подходов.

Ключевая вещь помнить состоит в том при выполнении вещей на фоновом потоке необходимо переключиться на поток UI для обновления средств управления окнами и т.д.

3
ответ дан 4 December 2019 в 07:36
поделиться

Быстрый и грязный путь использует Application.DoEvents() Но это может вызвать проблемы с событиями порядка, обрабатываются. Таким образом, это не рекомендуется

Проблема состоит, вероятно, не в том, что необходимо уступить потоку ui, но что Вы делаете обработку на потоке ui, блокирующем его от обработки сообщений. Можно использовать backgroundworker компонент, чтобы сделать пакетную обработку на другом потоке, не блокируя поток UI.

5
ответ дан 4 December 2019 в 07:36
поделиться

Если Вы работаете в фоне/рабочем потоке, можно звонить Control.Invoke на одном из Вашего UI управляет для выполнения делегата в потоке UI.

Control.Invoke синхронно (Ожидает, пока делегат не возвращается). Если Вы не хотите ожидать, Вы используете .BeginInvoke() к только ставят команду в очередь.

returnvalue .BeginInvoke() позволяет Вам проверять, завершился ли метод или ожидать, пока он не завершился.

1
ответ дан 4 December 2019 в 07:36
поделиться

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

1
ответ дан 4 December 2019 в 07:36
поделиться

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

Если Вы идете BackgroundWorker road (который я предлагаю), необходимо будет иметь дело с вызовами свинчивания резьбы к UI, если Вы хотите назвать какие-либо методы или свойства Средств управления, поскольку они - поток аффинно и должны быть названы только от потока, они были созданы на. Используйте Управление. Вызовите () и/или Управление. BeginInvoke () как соответствующий.

1
ответ дан 4 December 2019 в 07:36
поделиться

Приложение. DoEvents () или возможно выполненный пакет на отдельном потоке?

0
ответ дан 4 December 2019 в 07:36
поделиться

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

0
ответ дан 4 December 2019 в 07:36
поделиться

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

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

К сожалению, экран не только рисует, но и реагирует на действия пользователя. Это происходит потому, что DoEvents останавливает то, что вы сейчас делаете, чтобы обработать все сообщения windows, ожидающие обработки вашим приложением Winforms. Эти сообщения включают в себя запросы на перерисовку, а также любой пользователь, набирающий текст, нажимающий и т.д.

Так что, например, пока вы сохраняете данные, пользователь может делать такие вещи, как заставить приложение показать модальное диалоговое окно, которое совершенно не связано с долго выполняемой задачей (например, Help->About). Теперь вы реагируете на новые действия пользователя внутри уже запущенной долгоработающей задачи. DoEvents вернется, когда все события, которые ждали, когда вы его вызвали, будут завершены, а затем ваша длинно работающая задача будет продолжена.

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

Происходит то, что Application.DoEvents заставляет ваш код реентерабельно работать. См. определение Википедии здесь . Обратите внимание на некоторые моменты из верхней части статьи, что для того, чтобы код был реентерабельным, он:

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

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

Как многие здесь говорят, DoEvents может привести к очень странным сценариям в коде. Ошибки, к которым это может привести, может быть очень сложно диагностировать, и ваш пользователь вряд ли скажет вам: "О, это могло произойти, потому что я нажал на эту не связанную с этим кнопку, пока ждал, когда она сохранится".

3
ответ дан 4 December 2019 в 07:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: