Задержка загрузки combobox при загрузке формы - PullRequest
0 голосов
/ 11 ноября 2009

У меня есть проект Windows Forms (C #) с несколькими комбинированными списками / списками и т. Д., Которые заполняются при загрузке формы.

Проблема заключается в том, что загрузка комбинированных списков / списков происходит медленно, и поскольку загрузка выполняется, когда форма пытается отобразить всю форму, она не отображается, пока не будут заполнены все элементы управления. В некоторых случаях это может быть более 20 секунд.

Если бы было событие типа Form_finished_loaded, я мог бы поместить туда свой код, но я не могу найти событие, которое вызывается после того, как форма завершает рисование основных элементов управления.

У меня есть одно требование - загрузка должна выполняться в главном потоке (так как я получаю элементы из дружественного к потокам COM-приложения).

Я нашел одно потенциальное решение, но, возможно, есть лучший способ? Я могу создать System.Timer.Timer при создании формы и сделать так, чтобы первый тик вызывался примерно через 1 секунду, а затем заполнял списки из этого тика. Это дает форме достаточно времени для отображения, прежде чем она начнет заполнять списки.

У кого-нибудь есть другие советы о том, как отложить загрузку элементов управления?

Ответы [ 6 ]

6 голосов
/ 11 ноября 2009

Существует Показанное событие , которое «происходит всякий раз, когда форма отображается в первый раз». Также вы можете использовать функции BeginUpdate и EndUpdate , чтобы ускорить заполнение вашего комбинированного списка.

1 голос
/ 11 ноября 2009

У этого есть определенный запах обходного пути, но этот подход должен удовлетворить ваши потребности:

private bool _hasInitialized = false;
private void Form1_Shown(object sender, EventArgs e)
{    
    if (!_hasInitialized)
    {
        ThreadPool.QueueUserWorkItem(state =>
        {
            Thread.Sleep(200); // brief sleep to allow the main thread
                               // to paint the form nicely
            this.Invoke((Action)delegate { LoadData(); });    
        });
    }
}

private void LoadData()
{
    // do the data loading
    _hasInitialized = true;
}

Что он делает, так это то, что он реагирует при отображении формы, проверяет, была ли она уже инициализирована ранее, и если нет, то порождает поток, который будет ждать короткий момент перед вызовом метода LoadData в основном потоке. Это позволит правильно нарисовать форму. Возможно, того же можно добиться, просто позвонив по номеру this.Refresh(), но мне нравится идея позволить системе решать, как выполнять работу.

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

0 голосов
/ 11 ноября 2009

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

Если вы создаете новый поток в виде STAThread, вы, вероятно, можете загрузить ComboBox / ListBox в потоке без пользовательского интерфейса. IIRC ThreadPool выделяет рабочие потоки как MTAThread, поэтому вам нужно будет создать поток вручную, а не с помощью ThreadPool.QueueUserWorkItem.

0 голосов
/ 11 ноября 2009

Разве FormShown не является искомым событием?

0 голосов
/ 11 ноября 2009

Вы можете прослушивать событие VisibleChanged, и в первый раз, когда оно имеет значение true, вы вводите код инициализации.

0 голосов
/ 11 ноября 2009

Можете ли вы получить данные из веб-службы, которая вызывает компонент COM?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...