Помощь с многопоточностью на C# + GUI

93
18 февраля 2022, 01:50

Я делаю не большую утилиту по скачиванию музыки из ВК. Использую библиотеки VK NET для C#. Проект WInForms

Собственно всё работает, НО... На момент загрузки музыки "фризится" главная форма. У меня есть метод, который взаимодействует с минимальным набором классов (VK NET) + я добавляю ход загрузки (прогресс) в listBox. Всей загрузкой и прогрессом управляет цикл foreach (который находится в методе). System.Thread я использовать не могу, так как он требует "статику", а вся библиотека целиком динамическая + GUI так не работает.

Нашёл такую конструкцию с await Task.Run:

public async void dwnMyPage()
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddAudioBypass();
        String alltracks = Microsoft.VisualBasic.Interaction.InputBox("Сколько у Вас всего треков?", "Введите число", "", 100, 100);
        int num = Convert.ToInt32(alltracks);
        listBox1.Items.Add("-> Идёт подготовка...");
        int i = 0;
        var audios = _api.Audio.Get(new AudioGetParams { Count = num });
        string res = null;
        //////////////////
        await Task.Run(() =>
        {
            foreach (var audio in audios)
            {
                i += 1;
                //artist = audio.Artist.ToString();
                // name = audio.Title.ToString();
                // number = i.ToString();
                //Thread LbWrite = new Thread(lbWrite);
                //LbWrite.Start();
                //Thread.Sleep(500);
                //MessageBox.Show(_api.Token);
                listBox1.Items.Add(i.ToString() + ". " + audio.Artist.ToString() + " - " + audio.Title.ToString());
            //listBox1.GetSelected(listBox1.Items.Count - 1);//автопрокрутка
            ////listBox1.TopIndex = listBox1.Items.Count - 1;
            //listBox1.Refresh();
                try
                {
                    //MessageBox.Show(audio.Url.ToString());
                    AudioDownloadExt.Download(audioCategory: _api.Audio, audio.Url, path + i.ToString() + ". " + audio.Artist.ToString() + " - " + audio.Title.ToString() + ".mp3");
                    listBox1.Items.Add("Загружено "+i.ToString() + ". " + audio.Artist.ToString() + " - " + audio.Title.ToString());
                }
                catch (System.Net.WebException ex)
                {
                    i -= 1;
                    //listBox1.Refresh();
                    //Console.ForegroundColor = ConsoleColor.Red;
                    //listBox1.ForeColor = Color.Red;
                   // listBox1.Items.Add("Трек не поддерживается!!!!");
                   // listBox1.ForeColor = Color.Yellow;
                   // listBox1.Refresh();
                    //Console.ForegroundColor = ConsoleColor.Yellow;
                }
                catch (System.ArgumentNullException eeee)
                {
                    i -= 1;
                   // listBox1.Refresh();
                   // listBox1.ForeColor = Color.Red;
                    //Console.ForegroundColor = ConsoleColor.Red;
                   // listBox1.Items.Add("Ошибка.");
                   // listBox1.ForeColor = Color.Yellow;
                   // listBox1.Refresh();
                    //Console.ForegroundColor = ConsoleColor.Yellow;
                }
            }
        });
        // listBox1.Items.Add(res);
        // listBox1.Refresh();
        //////////////////
        listBox1.Items.Add(res);
        //listBox1.Refresh();
        //listBox1.ForeColor = Color.Green;
        //listBox1.Items.Add("-> ЗАВЕРШЕНО!!!");
        //listBox1.ForeColor = Color.Yellow;
        listBox1.Refresh();
    }//НЕ ДОРАБОТАНО!!!!!!!!!

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

Весь прогресс должен писаться из foreach и try ... catch

Что мне нужно поправить, исправить или дописать? Не совсем понимаю как с этим работать.

Answer 1

О чудо! Меня осенило... Сам не понял, что сделал, но фриз пропал.

Вместо прямого обращения к listBox1 я использовал вот такую конструкцию:

listBox1.Invoke(new Action(() => { listBox1.Items.Add("Загружено "+res); }));

Что тут происходит - пока не знаю, но оно работает!!! Вызываю везде, где есть прогресс.

READ ALSO
Вопрос по void Update и инкременту переменной

Вопрос по void Update и инкременту переменной

У меня есть переменная public Int Counter=0; и в методе Update есть динамическое условие при котором выполняется условие if (ObjIntersectsWith(Obj1)) я хочу вести...

138
Плавный поворот по вектору Unity

Плавный поворот по вектору Unity

данный код резко поворачивает объект по направлению вектораА как сделать плавный поворот по вектору?

122
Документирование форматов информационного обмена по средствам парсинга xsd. Ищу исходники

Документирование форматов информационного обмена по средствам парсинга xsd. Ищу исходники

Пишу софт, который документирует (описывает) формат обмена данными для SOAP сервисов

98
Как менять CurrentContentVM у RootVM?

Как менять CurrentContentVM у RootVM?

Я создал модели контента как сказано в ответе чувака этого вопроса

81