Общее правило: никогда не блокировать поток пользовательского интерфейса
Пользовательский интерфейс в Windows (и в Windows CE) имеет асинхронный характер. Это означает, что большинство вызовов API не обязательно делают то, что они должны делать немедленно. Вместо этого они генерируют серию событий, которые помещаются в очередь событий и затем извлекаются насосом событий, который, по сути, представляет собой бесконечный цикл, выполняющийся в потоке пользовательского интерфейса, выбирая события из очереди по одному и обрабатывая их. .
Из вышеизложенного можно сделать вывод, что если вы продолжите делать что-то длинное в потоке пользовательского интерфейса после запроса определенного действия (например, показа окна в вашем случае), то насос событий не сможет продолжить выбор событий (потому что вы не вернул контроль над ним), и, следовательно, запрошенное вами действие не может быть завершено.
Общий подход заключается в следующем: если вам необходимо выполнить сложное преобразование данных / загрузку / подготовку / что угодно, сделать это в отдельном потоке, а затем использовать Control.BeginInvoke, чтобы внедрить делегат в поток пользовательского интерфейса и коснуться фактического Пользовательский интерфейс управляет внутри этого делегата.
Несмотря на ваш иррациональный страх перед «сложностью», который несет с собой многопоточность, бояться очень мало. Вот небольшой пример, чтобы проиллюстрировать это:
public void ShowUI()
{
theForm = new MyForm();
theForm.Show();
// BeginInvoke() will take a new thread from the thread pool
// and invoke our delegate on that thread
new Action( PrepareData ).BeginInvoke(null,null);
}
public void PrepareData()
{
// Prepare your data, do complex computation, etc.
// Control.BeginInvoke will put our delegate on the UI event queue
// to be retrieved and executed on the UI thread
theForm.BeginInvoke( new Action( PutDataInTheForm ) );
}
public void PutDataInTheForm()
{
theForm.textBox1.Text = "data is ready!";
}
В то время как вы можете играть с альтернативными решениями, общая идея всегда остается неизменной: если вы делаете что-то длительное в потоке пользовательского интерфейса, ваш пользовательский интерфейс «зависнет». Он даже не будет перерисовываться при добавлении новых элементов пользовательского интерфейса на экран, поскольку перерисовка также является асинхронным процессом.
Следовательно, вы должны выполнять всю сложную и длинную работу в отдельном потоке и выполнять только простые, небольшие, гарантированно быстро выполняемые вещи в потоке пользовательского интерфейса. На самом деле другой альтернативы нет.
Надеюсь, это поможет.