Поток не обновляет индикатор выполнения - 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
});
Другие вопросы по тегам