Загрузка таблицы одновременно с формой

138
09 июня 2019, 23:40

Суть проблемы: при загрузке формы выполнялся запрос на выборку из таблицы на большое кол-во записей и при открытии формы ничего не появлялось на секунд 30, т.к. выполняется этот запрос, но потом появляется форма, что логично, но я решил не пугать пользователя такой долгой паузой

Как я пытался решить: Делал этот запрос на событие Shown, но появлялся кусок формы и она просто зависала, тоже не то

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

public partial class RunnersInfo : Form
{
    //Создание потока, в котором метод на запрос из БД
    Thread TableLoad = new Thread(new ThreadStart(DBConnection.GetRunners));
     private void RunnersControl_Load(object sender, EventArgs e)
    {
        //Запуск потока
        TableLoad.Start();
        //Присваивание результата dataGridView, dtRunners переменная, 
        которая содержит результат запроса;
        dataGridView1.DataSource = DBConnection.dtRunners;
        //Прочий код
    }
}

Но возникла следующая проблема dataGridView1.DataSource = DBConnection.dtRunners; выполняется раньше чем сам запрос и в итоге мы получаем пустую таблицу.

Я попытался воспользоваться TableLoad.Join(); но это привело к самому началу и процесс был заморожен, до выполнения окончания выполнения TableLoad, что логично

Также я пытался объединить DBConnection.GetRunners() и dataGridView1.DataSource = DBConnection.dtRunners; в один метод но возникла другая ошибка:

public partial class RunnersInfo : Form
{
    Thread TableLoad = new Thread(new ThreadStart(LoadRunners));
    private void RunnersControl_Load(object sender, EventArgs e)
    {
        TableLoad.Start();
        //Код
    }
    private static void LoadRunners()
    {
        DBConnection.GetRunners()
        //Ошибка: Для нестатического поля, метода или свойства 
          RunnersInfo.dataGridView1 требуется ссылка на объект.
        dataGridView1.DataSource = DBConnection.dtRunners;
    }
}

Да, я не знаю, как указать ссылку на этот dataGridView1 -.-
Ну вот, как-то так

Answer 1

Давайте используем современные средства: Task и async/await.
Можно использовать события Load или Shown - неважно.

private async void Form1_LoadAsync(object sender, EventArgs e)
{
    dataTable = await Task.Factory.StartNew(() =>
    {
        // здесь загрузка данных из БД
        return dt;
    }, TaskCreationOptions.LongRunning);
    dataGridView.DataSource = dataTable;
}

Обратите внимание на сигнатуру метода: он помечен async.

Загрузка данных будет выполнена в отдельном потоке (задаче). Форма при это зависать не будет. После завершения загрузки будет выполнена привязка.

Параметр LongRunning создаст новый поток, а не возьмёт поток из пула. Это желательно, т. к. нам известно, что мы выполняем длительное действие. Именно поэтому используется метод Factory.StartNew вместо более лаконичного Task.Run.

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

READ ALSO
Как может быть deadlock для выборки из базы?

Как может быть deadlock для выборки из базы?

Разбираюсь в не своем коде, там много обращений в БД(MS SQL SERVER) с использованием generic репозитория и много очень запутанного кода(поэтому его...

166
Как вызвать ошибку понятную для COM?

Как вызвать ошибку понятную для COM?

Как реализовать вызов ошибки, как com-объект?

176
Int и bool из С++. Как портировать на C#?

Int и bool из С++. Как портировать на C#?

У меня есть вот такая строчка в С++ коде: sects[low]bound = low

148
Как правильно отправить List<string[]> через json

Как правильно отправить List<string[]> через json

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

165