Поток не обновляет индикатор выполнения - C#
У меня есть пользовательская форма с пользовательским индикатором выполнения, созданный в основном классе (основной поток). Затем я создаю поток и отправляю ему функцию ThreadStart. Эта функция запуска потока должна обновлять индикатор выполнения в пользовательском элементе управления, но это не так.
class MyClass
{
......
//Custom form with progress bar
public CustomFormWithProgressBar statusScreen = new CustomFormWithProgressBar(0);
//thread to use
private Thread myThread;
.....
//Linked to a button to trigger the update procedure.
void ButtonPressEvent(.......)
{
//create a sub thread to run the work and handle the UI updates to the progress bar
myThread = new Thread(new ThreadStart(ThreadFunction));
myThread.Start();
}
.....
//The function that gets called when the thread runs
public void ThreadFunction()
{
//MyThreadClass myThreadClassObject = new MyThreadClass(this);
//myThreadClassObject.Run();
statusScreen.ShowStatusScreen();
for (int i = 0; i < 100; i++ )
{
statusScreen .SetProgressPercentage(i);
Thread.Sleep(20);
}
statusScreen.CloseStatusScreen();
}
Теперь моя форма statusScreen просто сидит и ничего не делает. Обновления не происходят. Но я подтвердил, что дополнительный поток действительно создан, и пока я нахожусь в ThreadFunction, я запускаюсь в новом потоке. Определил это через окно Thread в visual studio.
Почему мои обновления в процентах прогресса экрана состояния не отображаются? Как я могу получить свои обновления, чтобы выдвинуть новые значения на экран прогресса и показать его вживую?
Обратите внимание, что целочисленные значения, отправляемые в функции экрана состояния, представляют собой процент выполнения. Thread.Sleep просто для просмотра обновлений, если / когда произойдет.
Обратите внимание, что это не проблема перерисовки. я называю Invalidate, когда процент выполнения передается в пользовательский индикатор выполнения
2 ответа
Вы не можете обновить элементы управления из другого потока.
Правильный путь - это использование BackgroundWorker для ваших целей. Другой способ (почти правильный) - использовать метод Control.Invoke. И еще один, почти правильный путь - использовать SynchronizationContext.
Но вы можете выбрать темную сторону власти и использовать CheckForIllegalCrossThreadCalls - статическое свойство класса Control и установить для него значение false.
Поскольку индикатор выполнения находится в потоке пользовательского интерфейса / основного потока, он не может изменить его, не вызвав исключение перекрестных ссылок. Вы должны вызывать действие для основного потока.
Пример:
// in your thread
this.Invoke((MethodInvoker)delegate {
statusScreen.SetProgressPercentage(value); // runs on main thread
});