Форма отображается только после завершения асинхронных задач - PullRequest
0 голосов
/ 25 июня 2018

У меня есть этот код Task:

public static async Task Run(this CustomForm parent, Action action)
{
    parent.Enabled = false;
    using (Caricamento form = new Caricamento())
    {
        form.TopLevel = true;
        form.TopMost = true;
        form.Show();
        await Task.Run(action);
    }
    parent.Enabled = true;
}

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

    ListMessaggi listForm = new ListMessaggi(ListMessaggi.Tipo.Entrata);
    listForm.FormClosing += (o, args) =>
    {
        if (this.Controls.Count == 2)
        {
            args.Cancel = true;
        }
    };

    listForm.FormBorderStyle = FormBorderStyle.None;
    listForm.Dock = DockStyle.Fill;
    listForm.TopLevel = false;
    panel.Controls.Add(listForm);
    listForm.Show();

И затем, в форме, которая появляется при вызове метода listForm.Show(), я получил: enter image description here

Наконец, этот результат отображается во время выполнения асинхронной задачи: enter image description here

Как улучшить код, чтобы все работало правильно?

1 Ответ

0 голосов
/ 25 июня 2018

Исходя из дополнительной информации, которую вы предоставили в комментариях, я думаю, что вы должны попытаться преобразовать свой код, чтобы полностью использовать async / await. Это будет включать преобразование всех ваших функций ADO.NET в новые асинхронные методы , добавленные в ADO в .NET 4.5. Это должно исключить все вызовы Task.Run, а также беспорядочные вызовы InvokeRequired и BeginInvoke, которые вы выполняете для перенаправления управления обратно в поток пользовательского интерфейса.

Я думаю, вы обнаружите, что при правильной реализации вам даже не понадобится специальный метод расширения Run; у вас будет возможность встроить весь свой код, как в «традиционной» разработке .net.

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

public async void Form1_Load(object sender, EventArgs e)
{
    var data = await _dataProvider.GetSomeDataFromTheDatabase(aTotallyMadeUpVariable);
    this.MyDataGrid.DataSource = data;
}

Точно такой же шаблон работает для обработчиков событий в выпадающих списках и кнопках.


В качестве примечания, обработчики событий в WinForms - практически единственное место, где методы async void являются законно допустимыми. Все остальное, включая async методы, вызываемые из в обработчике событий, должно быть Task возвращающими функциями.


Как немного больше "учебника для начинающих" в async / await, это то, как он избегает блокировки потока пользовательского интерфейса в моем примере выше.

Модификатор async в функции действует как маркер для компилятора, чтобы преобразовать метод в конечный автомат. Компиляция будет сегментировать код в методе, разбивая его при каждом вызове await, на отдельные состояния. Когда функция вызывается, запускается первое состояние (до значения await), а затем функция возвращается к вызывающей стороне. Когда ожидающая функция возвращается, код после нее (в следующем состоянии) вызывается как продолжение. Любые данные, которые разделяются между состояниями, например локальные переменные, перемещаются в объект, который передается в продолжение каждого состояния.

...