Это может быть связано с выравниванием и заполнением байт, чтобы структура выходила на четное количество байтов (или слов) на вашей платформе. Например, в 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
BackgroundWorker походит на объект, который Вы хотите.
Выполните долгий процесс на фоновом потоке. Фоновый класс рабочего является простым способом сделать это - он оказывает простую поддержку для отправки обновлений прогресса и событий завершения, для которых обработчики событий называют на корректном потоке для Вас. Это содержит код в чистоте и краткий.
Для отображения обновлений индикаторы выполнения или текст строки состояния являются двумя из наиболее распространенных подходов.
Ключевая вещь помнить состоит в том при выполнении вещей на фоновом потоке необходимо переключиться на поток UI для обновления средств управления окнами и т.д.
Быстрый и грязный путь использует Application.DoEvents()
Но это может вызвать проблемы с событиями порядка, обрабатываются. Таким образом, это не рекомендуется
Проблема состоит, вероятно, не в том, что необходимо уступить потоку ui, но что Вы делаете обработку на потоке ui, блокирующем его от обработки сообщений. Можно использовать backgroundworker компонент, чтобы сделать пакетную обработку на другом потоке, не блокируя поток UI.
Если Вы работаете в фоне/рабочем потоке, можно звонить Control.Invoke
на одном из Вашего UI управляет для выполнения делегата в потоке UI.
Control.Invoke
синхронно (Ожидает, пока делегат не возвращается). Если Вы не хотите ожидать, Вы используете .BeginInvoke()
к только ставят команду в очередь.
returnvalue .BeginInvoke()
позволяет Вам проверять, завершился ли метод или ожидать, пока он не завершился.
Используйте backgroundworker компонент для выполнения пакетной обработки в отдельном потоке, это затем не повлияет на поток UI.
Я хочу вновь заявить о том, что отметили мои предыдущие комментаторы: избегайте DoEvents (), когда это возможно, поскольку это - почти всегда форма "взлома" и вызывает кошмары обслуживания.
Если Вы идете BackgroundWorker road (который я предлагаю), необходимо будет иметь дело с вызовами свинчивания резьбы к UI, если Вы хотите назвать какие-либо методы или свойства Средств управления, поскольку они - поток аффинно и должны быть названы только от потока, они были созданы на. Используйте Управление. Вызовите () и/или Управление. BeginInvoke () как соответствующий.
Приложение. DoEvents () или возможно выполненный пакет на отдельном потоке?
DoEvents () был тем, что я искал, но я также проголосовал за ответы backgroundworker, потому что это похоже на хорошее решение, что я исследую еще немного.
Чтобы понять, что люди говорят о DoEvents, вот описание того, что может произойти.
Скажем, что у вас есть какая-то форма с данными на ней, и ваше долгое событие сохраняет ее в базу данных или генерирует отчет на ее основе. Вы начинаете сохранять или генерировать отчет, а затем периодически вызываете DoEvents, чтобы экран продолжил рисовать.
К сожалению, экран не только рисует, но и реагирует на действия пользователя. Это происходит потому, что DoEvents останавливает то, что вы сейчас делаете, чтобы обработать все сообщения windows, ожидающие обработки вашим приложением Winforms. Эти сообщения включают в себя запросы на перерисовку, а также любой пользователь, набирающий текст, нажимающий и т.д.
Так что, например, пока вы сохраняете данные, пользователь может делать такие вещи, как заставить приложение показать модальное диалоговое окно, которое совершенно не связано с долго выполняемой задачей (например, Help->About). Теперь вы реагируете на новые действия пользователя внутри уже запущенной долгоработающей задачи. DoEvents вернется, когда все события, которые ждали, когда вы его вызвали, будут завершены, а затем ваша длинно работающая задача будет продолжена.
А что, если пользователь не закроет модальный диалог? Ваша долгосрочная задача будет ждать вечно, пока этот диалог не закроется. Если вы фиксируете транзакцию в базе данных и держите ее в руках, то теперь вы держите транзакцию открытой, пока пользователь пьет кофе. Либо ваша транзакция тайм-аут и вы теряете свою настойчивость, либо транзакция не тайм-аут и вы потенциально загораживаете других пользователей БД.
Происходит то, что Application.DoEvents заставляет ваш код реентерабельно работать. См. определение Википедии здесь . Обратите внимание на некоторые моменты из верхней части статьи, что для того, чтобы код был реентерабельным, он:
Очень маловероятно, что длинно работающий код в приложении WinForms работает только на данных, переданных вызывающим абонентом методу, не содержит статических данных, не имеет блокировок, а вызывает только другие реентерабельные методы.
Как многие здесь говорят, DoEvents может привести к очень странным сценариям в коде. Ошибки, к которым это может привести, может быть очень сложно диагностировать, и ваш пользователь вряд ли скажет вам: "О, это могло произойти, потому что я нажал на эту не связанную с этим кнопку, пока ждал, когда она сохранится".