Поток не обновляет элемент управления индикатором выполнения - 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, когда процент выполнения передается в настраиваемый индикатор выполнения


person jordan    schedule 02.05.2013    source источник


Ответы (2)


Вы не можете обновлять элементы управления из другого потока.

Правильный способ - использовать BackgroundWorker для своих целей. Другой способ (почти правильный) - использовать метод Control.Invoke. И еще один почти верный способ - использовать SynchronizationContext.

Но вы можете выбрать темную сторону силы и использовать CheckForIllegalCrossThreadCalls - статическое свойство класса Control и установить для него значение false.

person Uzzy    schedule 02.05.2013
comment
Я пробовал invoke и backgroundWorker, но не смог. Могли бы вы привести пример, примененный к моему коду в OP? Я был бы очень признателен - person jordan; 03.05.2013
comment
Конечно. 1. Вы создаете окно прогресса в потоке без графического интерфейса. Переместить statusScreen.ShowStatusScreen (); в ButtoPressEvent. Затем создайте BackgroundWorker в ButtonPressEvent. Создайте обработчики для событий DoWork и Completed, ProgressChanged. см. справку BackgroundWorker в MSDN. и Закройте экран состояния в событии «Завершено». - person Uzzy; 03.05.2013

Поскольку ваш индикатор выполнения находится в потоке пользовательского интерфейса / основном потоке, ваш поток не может изменить его, не вызывая исключения ссылки между потоками. Вы должны вызывать действие в основном потоке.

Пример:

// in your thread
this.Invoke((MethodInvoker)delegate {
    statusScreen.SetProgressPercentage(value); // runs on main thread
});
person Ryan    schedule 02.05.2013
comment
Я только что попробовал это на своем компьютере, и он сильно разбился. Так что я попробую еще раз и дам тебе знать - person jordan; 03.05.2013
comment
Что вы имеете в виду, возникло исключение? - person Ryan; 03.05.2013
comment
нет, он просто заблокировал систему и отключился черным экраном. сложно или сложно перезагрузить ха-ха - person jordan; 03.05.2013
comment
Очень странно, я не понимаю, как добавление строк выше могло вызвать это. - person Ryan; 03.05.2013
comment
это наверное просто совпадение - person jordan; 03.05.2013
comment
Таким образом, мой вызов Invalidate () в statusScreen.SetProgressPrecentage (int) зависает. - person jordan; 03.05.2013