@Zulkund

Как обновлять ProgressBar в побочном потоке c#?

Зранее сорь, тема избита, но я не понимаю что нужно сделать.
Запускаю поток:
private void button3_Click(object sender, EventArgs e)
        {
                ProgressBar.Maximum = listToCalc.Count;
                ProgressBar.Value = 0;
                ProgressBar.Step = 1;
                listOfWells.Clear();
                thread = new Thread(calc);
                thread.Start();
            }

И возникает ошибка!
public void calc()
        {
            for (int i = 0; i < listToCalc.Count; i++) {
                listOfWells.Add(new Well(listToCalc[i]));
                listOfWells[i].calcP();
                ProgressBar.PerformStep();  - Выскакивает исключение!
            }
        }

Исправьте пожалуйста в рабочей вариант. Всякие делегаты и диспетчеры просто не могу понять. Заранее спасибо!
  • Вопрос задан
  • 3925 просмотров
Решения вопроса 2
Rou1997
@Rou1997
this.Invoke((MethodInvoker) delegate() {
     ProgressBar.PerformStep();
});

Понять очень просто, делегат это функция поэтому с круглыми и фигурными скобками, от обычной функции разница в том, что она используется как переменная (параметр метода), она передается в метод this.Invoke (это запомнить) чтобы он ее вызвал в потоке UI, а MethodInvoker просто приведение типа.

Еще один вариант:
this.Invoke((MethodInvoker) (() =>
{
    ProgressBar.PerformStep();
}));

По сути, это вот такой код:
this.Invoke((MethodInvoker) () =>
{
    ProgressBar.PerformStep();
});

Где значением переменной (таким же, как 0.5, "abc" или new Button()) является следующее:
() =>
{
    ProgressBar.PerformStep();
}

Остальное - обычное приведение к MethodInvoker, зачем тогда эти скобки вокруг значения, мы же не пишем int x = (int)(0.5);, увы но при приведении типов вообще не всегда можно ограничиться круглым скобками лишь для типа и опустить их для приводимого значения, конечно можно об этом забыть и не скомпилируется, но с опытом уже знаешь, если приведение не компилируется, то нужно попробовать добавить скобки для значения.
Ответ написан
Комментировать
kykyryky
@kykyryky
В классе формы объявить объект типа IProgress и инициализировать, например в конструкторе:
IProgress<int> progress;

progress = new Progress((i) =>
             {
                 progressBar.Value = i;
             });


Немного переделать метод calc:
public Task calc(IProgress<int> progress)
{
return Task.Run(() =>
            {
            for (int i = 0; i < listToCalc.Count; i++) {
                listOfWells.Add(new Well(listToCalc[i]));
                listOfWells[i].calcP();
                progress.Report(i)
            }
            });
        }


В обработчике:
private async void button3_Click(object sender, EventArgs e)
        {
                ProgressBar.Maximum = listToCalc.Count;
                ProgressBar.Value = 0;
                ProgressBar.Step = 1;
                listOfWells.Clear();
                await calc();
            }

Как-то так попробуй. Мог скобку потерять, или еще что по мелочи.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
AxisPod
@AxisPod
Используйте https://msdn.microsoft.com/ru-ru/library/system.wi...
Ибо из другого потока UI обновлять нельзя и MS для этого сделала готовый инструмент. Да и велосипеды не требуются в этом случае.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы