Рейтинг:
1
Philippe Mori
Вы должны прочитать документацию по BackgroundWorker, прежде чем использовать его, чтобы правильно понять, как он работает и должен использоваться.
Класс BackgroundWorker (System.ComponentModel)[^]
Как сделать Потокобезопасные вызовы элементов управления Windows Forms[^]
Вот несколько подобных вопросов :
c# - CrossThreadMessagingException при использовании backgroundworker windows forms - переполнение стека[^]
многопоточность - проблема многопоточности C# - переполнение стека[^]
В вашем случае обычно требуется включить отчет о ходе выполнения, а затем реализовать обработчик для отчета о ходе выполнения.
BackgroundWorker.Метод ReportProgress (Int32) (System.ComponentModel)[^]
Обычно я вычислял процент внутри DSoWork
обработчик и сообщает о прогрессе только в том случае, если процент (в виде целого числа) изменился. Таким образом, вы гарантируете, что не обновляете пользовательский интерфейс более 100 раз, что достаточно при отображении индикатора выполнения.
Кстати, есть версия, которая позволяет передавать UserState, который можно использовать, если вы хотите сообщить что-то еще, кроме процента. Это несколько проще и понятнее, чем использование Invoke
непосредственно.
Обычно это работает довольно хорошо, если вы сообщаете о прогрессе до нескольких сотен раз. Если у вас есть много тысяч обновлений, то вам каким-то образом нужно оптимизировать связь между потоками, чтобы уменьшить накладные расходы на межпотоковые вызовы.
Рейтинг:
0
Garth J Lancaster
Я не уверен, почему вы устанавливаете progressBar1. Value = progressBar1. Maximum там - это может быть что-то, чего я не знаю о стиле шатра ..
progressBar1.BeginInvoke(
new Action( () =>
{
progressBar1.Value = i;
}
));
внутри вашего "цикла for" - я не вижу, где еще вы обновляете значение индикатора выполнения
[редактировать] .. почему бы не взять это
for (int i = 1; i <= 100; i++)
{
this.label1.Text += string.Format("{0}. This is a test.", i);
Thread.Sleep(10000);
}
и сделать это так
for (int i = 1; i <= 100; i++)
{
this.label1.Text += string.Format("{0}. This is a test.", i);
progressBar1.Value = i;
Thread.Sleep(10000); // Not sure you need to delay for this long
}
если только каким-то образом я не упустил то, что вы пытаетесь сделать/в чем ваша проблема
[/редактировать]
chimcham
Привет, сэр Гарт, я уже обновил свой код.. Пожалуйста помочь..
Garth J Lancaster
вы все еще не обновляете progressBar1. Value в цикле ! смотрите обновленное решение (через минуту после того, как я его отредактировал)
chimcham
Да, сэр, я не обновлял значение индикатора выполнения, потому что просто хочу использовать стиль шатра..
chimcham
Я столкнулся с новой ошибкой, сэр..
Garth J Lancaster
вы можете справиться с этой ошибкой с помощью BeginInvoke-see the strike through text и применить то же самое к label1. text
chimcham
Я попробовал это, Сэр, по вашему совету..
этикетка 1.BeginInvoke(
новое действие (() =>
{
for (int i = 1; i <= 1000; i++)
{
этот.этикетка 1.Текстовая строка.Формат ("{0}. Это тест.\n", я);
}
}
));
Нить.Сон(10000);
Да, больше никакой ошибки. но мой индикатор прогресса замерзнет... вместо того, чтобы отображать шатер, во время цикла.. Пожалуйста помочь.
Philippe Mori
Очевидно, что если вы отправите 1000 обновлений подряд, пользовательский интерфейс замерзнет в течение этого времени, так как эти обновления будут поступать гораздо быстрее, чем пользовательский интерфейс будет обновляться!
Чтобы он работал, очевидно, что задержка должна быть внутри цикла (10 МС на каждой итерации вместо 10 секунд сразу в конце).
Кроме того, если генерация данных происходит намного быстрее, чем обновление пользовательского интерфейса, то в какой-то момент вам нужно пропустить отображение некоторых элементов. Кроме того, не было бы большого смысла отображать дюжину значений каждую секунду, если вы не можете их прочитать...
Другой момент заключается в том, что нет смысла помещать петлю в Invoke
вызовите, когда вы возвращаете всю обработку в поток пользовательского интерфейса, побеждая цель использования фонового потока...