dragnscalearmor Ответов: 1

C# async/await не работает с mysql


Я пытаюсь разобраться в этой асинхронной / ожидающей вещи и подумал, что попробую сделать это с помощью небольшого приложения для базы данных. Ниже приведен код, который работает нормально, но метод GetData() не работает асинхронно, потому что пользовательский интерфейс все еще зависает при подключении/извлечении данных. У меня есть случайные числа, заполняющие listBox2 в качестве визуального сигнала о том, что пользовательский интерфейс замерзает. База данных-это просто список адресов веб-сайтов, которые я сделал для тестирования этого кода.

using System;
using System.Windows.Forms;
using MySql.Data.MySqlClient;

namespace MySQLasync
{
    public partial class Form1 : Form
    {
        // public variables and constants
        string strconnect = "Server = localhost; Port=3306; Database=mydbase; Uid=myusername; Pwd=mypasswd;";
        Random r = new Random();
        int c = 0;

        public Form1()
        {
            InitializeComponent();
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            timer1.Enabled = true;
            GetData();
        }

        private async void GetData()
        {
            listBox1.Items.Clear();
            string sql = "SELECT * FROM websites";
            MySqlConnection con1 = new MySqlConnection(strconnect);
            {
                con1.Open();
                MySqlCommand cmd = new MySqlCommand(sql, con1);
                MySqlDataReader reader = (MySqlDataReader)await cmd.ExecuteReaderAsync();
                while (reader.Read())
                {
                    listBox1.Items.Add(reader["title"].ToString());
                }
                con1.Close();
            }
        }

        private void Timer1_Tick(object sender, EventArgs e)
        {
            c++;
            if (c > 20)
            {
                c = 0;
                listBox2.Items.Clear();
            }
            int num = r.Next(1, 999999);
            listBox2.Items.Add(num);
        }
    }
}


Что я уже пробовал:

Независимо от того, использую ли я async / await или нет, код работает точно так же. То есть пользовательский интерфейс по-прежнему зависает на то же время, что и доступ к данным и добавление их в listBox1.

Может кто-нибудь объяснить, что я здесь делаю не так? Я хочу, чтобы пользовательский интерфейс оставался отзывчивым во время доступа к данным и их загрузки. Я еще не уверен, что у меня есть вся концепция async/await. Спасибо.

Richard Deeming

Как насчёт:

while (await reader.ReadAsync())

Кроме того, убедитесь, что вы используете MySQL Connector/NET 6.9 или более поздней версии.
MySQL :: MySQL Connector/NET руководство разработчика :: 5.10 асинхронные методы[^]

dragnscalearmor

Ричард, спасибо тебе. Я сделал это изменение, но тот же результат: пользовательский интерфейс немного зависает. Кроме того, я использую 8.0.15 соединителя MySQL.

1 Ответов

Рейтинг:
5

Gerry Schmitz

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

Асинхронное Программирование | Microsoft Docs[^]


dragnscalearmor

Спасибо за ссылку. Я следовал документам и форматировал свой код в соответствии с этим шаблоном, и он все еще замораживает пользовательский интерфейс во время загрузки. Не уверен, что это вызывает, так как вывод при запуске этого метода таков: "поток 0x3158 вышел с кодом 0 (0x0)." .... а затем он перечисляет веб-сайты из запроса. Кажется, я не могу обойти это замораживание пользовательского интерфейса.

Gerry Schmitz

Ну, "покажи код". Все остальное-слухи.

dragnscalearmor

Это мой недавно структурированный код, но он также ненадолго замораживает пользовательский интерфейс:

public async void GetMoreData()
{
using (MySqlConnection conn = new MySqlConnection(strconnect)) // переменная строки моего соединения
{
MySqlCommand command = new MySqlCommand("select * from websites", conn);

Коннектикут.Открыть();
MySqlDataReader reader = (MySqlDataReader)команда ожидания.ExecuteReaderAsync();
в то время как (жду читателя.Методы readasync())
{
список listbox1.Предметы.Добавить(читатель["название"].Метод toString());
}
}
}

Richard Deeming

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

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

await conn.OpenAsync();

dragnscalearmor

Изменил код, чтобы проверить это, и пользовательский интерфейс по-прежнему зависает даже без добавления в список. Ниже приведены данные из окна вывода с новым кодом:

'MySQLasync.exe' (CLR v4.0.30319: MySQLasync.exe): заряжен 'C:\WINDOWS\Microsoft.Net\assembly\GAC_32\System.Data\v4.0_4.0.0.0__b77a5c561934e089\System.Data.dll". Пропущенные символы загрузки. Модуль оптимизирован, и включена опция отладчика "только мой код".
'MySQLasync.exe' (CLR v4.0.30319: MySQLasync.exe): загружено 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\MySql.Data\v4.0_8.0.15.0__c5687fc88969c44d\MySql.Data.dll'. Пропущенные символы загрузки. Модуль оптимизирован, и включена опция отладчика "только мой код".
'MySQLasync.exe' (CLR v4.0.30319: MySQLasync.exe): заряжен 'C:\WINDOWS\Microsoft.Net\assembly\GAC_32\System.Транзакции\v4.0_4.0.0.0__b77a5c561934e089\система.Transactions.dll". Пропущенные символы загрузки. Модуль оптимизирован, и включена опция отладчика "только мой код".
'MySQLasync.exe' (CLR v4.0.30319: MySQLasync.exe): заряжен 'C:\WINDOWS\Microsoft.Net\assembly\GAC_32\System.EnterpriseServices\v4.0_4.0.0.0__b03f5f7f11d50a3a\система.EnterpriseServices.dll". Пропущенные символы загрузки. Модуль оптимизирован, и включена опция отладчика "только мой код".
'MySQLasync.exe' (CLR v4.0.30319: MySQLasync.exe): заряжен 'C:\WINDOWS\Microsoft.Net\assembly\GAC_32\System.EnterpriseServices\v4.0_4.0.0.0__b03f5f7f11d50a3a\система.Услуги предприятий.Wrapper.dll". Пропущенные символы загрузки. Модуль оптимизирован, и включена опция отладчика "только мой код".
'MySQLasync.exe' (CLR v4.0.30319: MySQLasync.exe): загружено 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Management\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Management.dll'. Пропущенные символы загрузки. Модуль оптимизирован, и включена опция отладчика "только мой код".
Поток 0x2d0c вышел с кодом 0 (0x0).

Новый код таков:

ждите Конна.Этого openasync();
MySqlDataReader reader = (MySqlDataReader)команда ожидания.ExecuteReaderAsync();
в то время как (жду читателя.Методы readasync())
{
//список listbox1.Предметы.Добавить(читатель["название"].Метод toString());
}

Очень странная проблема. Я не профессиональный программист, в основном просто приятное хобби, но это поставило меня в тупик.

Richard Deeming

Если вы используете что-то вроде CodeTrack[^] чтобы профилировать ваше приложение, вы должны иметь возможность видеть, какие вызовы занимают больше всего времени.

dragnscalearmor

Отметьте это как ответ, используя ответ Джерри выше. MS docs показывает, что это правильный способ сделать это, поэтому я продолжу работать со своим кодом, чтобы он больше соответствовал их рекомендациям. Поблагодарить каждого.