Почему приложение на C# WindowsForms зависает при отрисовке графика в chart, когда эта операция вынесена в отдельный поток?

Рейтинг: 0Ответов: 0Опубликовано: 14.07.2023

Всем добрый день!) Передо мной стоит задача отрисовки годогрофа Найквиста при открытии формы. Также пока точки для графика вычисляются и добавляются в контрол, я отображаю анимированную гифку загрузки. Делаю я это на WindowsForms с использованием компонента Chart. Т.к. количество точек может превышать 10 000, то отрисовку графика (вычисление и добавление точке в Chart) вынес в отдельный поток. Пробовал создавать новый поток, а также сделать метод асинхронным, и идея вроде бы работает, график скрыт, пока все точки не добавятся, гифка загрузки работает, приложение не зависает, НО как только процесс подходит к концу и пора отображать весь график - приложение зависает на n-ое количество секунд (зависит от кол-ва точек). Подскажите, пожалуйста, как это можно поправить?

Вот пример моего кода с созданием отдельного потока:

private void OnNyquistFormLoad(object sender, EventArgs e)
{
    var thr = new Thread(DrawGraphic);
    thr.Start();
}

private void DrawGraphic()
{
    try
    {
        for(float i = 0; i < 1000; i += 0.1f)
        {
            chartNyquist.Invoke(new Action(() =>
            {
                chartNyquist.Visible = false;
            }));

            chartNyquist.Invoke(new Action(() =>
            {
                chartNyquist.Series[0].Points.SuspendUpdates();
                chartNyquist.Series[0].Points.AddXY((c * (mas[0] * Math.Pow(i, 4) - mas[2] * Math.Pow(i, 2) + mas[4])) / (Math.Pow(mas[0] * Math.Pow(i, 4) + mas[2] * Math.Pow(i, 2) + mas[4], 2) - Math.Pow((mas[1] * Math.Pow(i, 3) - mas[3] * i), 2)), i * c * (mas[1] * Math.Pow(i, 3) - mas[1] * i) / (Math.Pow((mas[0] * Math.Pow(i, 4) - mas[2] * Math.Pow(i, 2) + mas[4]), 2) + Math.Pow((mas[1] * Math.Pow(i, 3) - mas[3] * i), 2)));
                chartNyquist.Series[0].Points.ResumeUpdates();
            }));
        }
    }
    catch(Exception) { }
    finally
    {
        pbLoading.Invoke(new Action(() =>
        {
            pbLoading.Visible = false;
        }));
        chartNyquist.Invoke(new Action(() =>
        {
            chartNyquist.Visible = true; // Скорее всего здесь приложение зависает
        }));
    }
}

Ещё вариант с асинхронным методом:

private async void OnNyquistFormLoad(object sender, EventArgs e)
{
    try
    {
        await DrawGraphicAsync();
    }
    catch(Exception) { }
    finally
    {
        pbLoading.Visible = false;
    }
}

private async Task DrawGraphicAsync()
{
    await Task.Run(() =>
    {
                chartNyquist.Invoke(new Action(() =>
        {
            chartNyquist.Visible = false;
        }));

        for(float i = 0; i < 1000; i += 0.1f)
        {
            chartNyquist.Invoke((MethodInvoker)(() =>
            {
                chartNyquist.Series[0].Points.AddXY((c * (mas[0] * Math.Pow(i, 4) - mas[2] * Math.Pow(i, 2) + mas[4])) / (Math.Pow(mas[0] * Math.Pow(i, 4) + mas[2] * Math.Pow(i, 2) + mas[4], 2) - Math.Pow((mas[1] * Math.Pow(i, 3) - mas[3] * i), 2)), i * c * (mas[1] * Math.Pow(i, 3) - mas[1] * i) / (Math.Pow((mas[0] * Math.Pow(i, 4) - mas[2] * Math.Pow(i, 2) + mas[4]), 2) + Math.Pow((mas[1] * Math.Pow(i, 3) - mas[3] * i), 2)));
            }));
        }

        chartNyquist.Invoke((MethodInvoker)(() =>
        {
            chartNyquist.Visible = true; // Скорее всего здесь приложение зависает
        }));
    }).ConfigureAwait(false);
}

Ответы

Ответов пока нет.