.NET Compact Framework: как обеспечить видимость формы перед запуском кода? - PullRequest
1 голос
/ 20 января 2010

У нас есть настройка Model-View-Presenter с нашим приложением .NET Compact Framework.Стандартная форма CF реализует интерфейс представления и передается в конструктор докладчика.докладчик говорит форме показывать себя, вызывая view.Run ();затем представление выполняет Show () для себя, и докладчик вступает во владение снова, загружая данные и заполняя их в представление.

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

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

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

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

Ответы [ 3 ]

2 голосов
/ 20 января 2010

Общее правило: никогда не блокировать поток пользовательского интерфейса

Пользовательский интерфейс в 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!";
}

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

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

Надеюсь, это поможет.

1 голос
/ 20 января 2010

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

protected void Form_Load(blah blah blah)
{
   this.Show();
   Application.DoEvents();

   ... data loading methods ...
}
0 голосов
/ 21 января 2010

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

...