WinApp Form загружает слишком много данных во время события Load - PullRequest
3 голосов
/ 08 февраля 2011

У меня есть форма, которая загружает большое количество данных с сервера SQL. Ниже приведен код, который даст хороший совет:

private void BranchCenter_Load(object sender, EventArgs e) {
  //Combo boxes:
  LoadCities();
  LoadCoordinators();
  LoadComputerSystems();

  //Actual entity
  LoadBranch();
}

private void LoadCities() {
  //LINQ2SQL to load data. ~5000 records.
}

private void LoadCoordinators() {
  //LINQ2SQL to load data. ~50 records.
}

private void LoadComputerSystems() {
  //LINQ2SQL to load data. ~550 records.
}

private void LoadBranch() {
  LoadBranchInit();
  LoadBranchDetails();
  LoadBranchTimings();
  LoadBranchServices();
  LoadBranchLocumsHistory();
  LoadBranchJobs();
  LoadBranchNotes();
}

private void LoadBranchInit() {
  //LINQ2SQL to load the Branch object based upon the Branch ID
}

private void LoadBranchDetails() {
  //LINQ2SQL to load basic branch stuff. 38 fields. Mixed editors.
}

private void LoadBranchTimings() {
  //LINQ2SQL to load timings info into 80 date-time controls
}

private void LoadBranchServices() {
  //LINQ2SQL to load services offered at branch info into 20 check-boxes controls
}

private void LoadBranchLocumsHistory() {
  //LINQ2SQL to load branch history info into grid control. Always increasing # of rows :(
}

private void LoadBranchJobs() {
  //LINQ2SQL to load branch jobs info into grid control. Always increasing # of rows :( 
}

private void LoadBranchNotes() {
  //LINQ2SQL to load branch notes info into grid control
}

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

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

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

Любая стратегия или совет? Спасибо за прочтение.

Ответы [ 10 ]

3 голосов
/ 08 февраля 2011

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

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

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

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

3 голосов
/ 08 февраля 2011

Если каждый тип данных отображается только на одной странице, я бы переместил код так, чтобы каждый соответствующий тип данных загружался при первой загрузке каждой вкладки.Таким образом, работа по загрузке данных будет распределена в течение более длительного времени, и, возможно, ее вообще не потребуется, если пользователь не будет переходить на все вкладки во время сеанса.любой другой асинхронный механизм.На вкладке вы можете иметь два элемента управления панели.Один, который содержит пользовательский интерфейс для страницы, и который имеет Visible = false при загрузке формы, а другой содержит метку с текстом типа «Загрузка, пожалуйста, подождите ...».Когда данные загружены для страницы и обновлен пользовательский интерфейс, переключите видимость на двух панелях, чтобы отобразить пользовательский интерфейс.Таким образом, форма будет реагировать на загрузку данных, и поскольку вы загружаете данные только для одной страницы за раз, время загрузки должно быть довольно коротким.

1 голос
/ 09 февраля 2011

TabControl уже выполняет отложенную загрузку.

Сделайте себе одолжение и поместите содержимое каждой вкладки в UserControl.

1 голос
/ 08 февраля 2011

Создайте BackgroundWorker для каждой из вкладок.В событии Load формы отключите все вкладки и вызовите метод RunWorkerAsync () для каждого из фоновых рабочих.

В каждом обработчике событий DoWork загрузите данные, необходимые для связанной вкладки, из базы данных в таблицу данных и задайте для свойства Result объекта DoWorkEventArgs таблицу данных.

Примечание. ВВ обработчике событий DoWork НЕ следует обновлять какой-либо элемент управления пользовательского интерфейса, поскольку он работает в другом потоке.Вам нужно только извлечь данные из базы данных и установить свойство Result.

В обработчиках событий RunWorkerCompleted вы можете получить доступ к таблице данных, которая была получена в обработчике событий DoWork, получив свойство Result объектаRunWorkerCompletedEventArgs.Затем вы можете соответствующим образом установить свойства элементов управления пользовательского интерфейса и затем включить вкладку, связанную с текущим фоновым рабочим.

1 голос
/ 08 февраля 2011

Да, BackgroundWorker отлично подходит для этого.

Я думаю, что вы делаете это неправильно, потому что хотите изменить форму в событии DoWork.

Тем не менее, вы должны собирать результаты только в е. Результаты этого события

Затем в RunWorkerCompleted вы используете его e.Results для изменения формы.

1 голос
/ 08 февраля 2011

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

1 голос
/ 08 февраля 2011

Проблема здесь в том, что метод DoWork в BackgroundWorker не может касаться графического интерфейса.

Он должен использовать BackgroundWorker.ReportProgress( int progress, object state) для вызова метода в потоке графического интерфейса, который может свободно обновлять графический интерфейс.

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

0 голосов
/ 23 февраля 2011

Хорошо, я столкнулся с новым сценарием. Я перешел на Visual Studio 2010 и столкнулся с Task.Factory.StartNew (() => myMethod ());

Это то, что я имею до сих пор:

private void LoadLocum() {
    var TaskInit = Task.Factory.StartNew(() => LoadLocumInit());
    TaskInit.Wait();

    var TaskDetails = Task.Factory.StartNew(() => LoadLocumDetails());
    TaskDetails.Wait();

    var TaskQualifications = Task.Factory.StartNew(() => LoadLocumQualifications());
    //Enable Qualification TabPage automatically whenever TaskQualifications is complete

    Parallel.Invoke(
        () => LoadLocumComputerSystems(), 
        () => LoadLocumOtherInfo(), 
        () => LoadLocumEmergencyContacts(), 
        () => LoadLocumDistanceRates(), 
        () => LoadLocumDocuments(), 
        () => LoadLocumNotes(), 
        () => LoadLocumBannedStatus()
    );

}

Первые два шага (задачи) являются критическими. Теперь вкладки «Страницы вкладки» отключены. Мне нужно включить их на основе выполнения связанных с ними задач. Я могу найти событие для подписки, которое указывает, что определенная задача выполнена или нет.

0 голосов
/ 08 февраля 2011

Хорошо.Массивный ответ почти сразу.Люблю это место.Перепрыгнув с link-2-link, я столкнулся лицом к лицу с Reactive Extensions for .NET (Rx) .Может ли это быть хорошей альтернативой?Не могу найти руководство по использованию Rx в моем сценарии.

0 голосов
/ 08 февраля 2011

Для решения проблемы, с которой вы сталкиваетесь в фоновом рабочем потоке, может показаться, что вы пытаетесь получить доступ к компонентам пользовательского интерфейса из самого потока.Чтобы сделать это из потока, не являющегося пользовательским интерфейсом, вам нужно использовать Control.Invoke, а не пытаться получить прямой доступ к компонентам.

...