线程未更新进度条控件 - C#

时间:2013-05-02 20:19:45

标签: c# multithreading winforms progress-bar progress

我有一个带有自定义进度条的自定义表单,在主类(主线程)中生成。然后我生成一个线程并发送一个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中,我在新线程上运行。通过visual studio中的Thread窗口确定这一点。

为什么我的状态屏幕进度百分比更新未显示?如何获取我的更新以将新值推送到进度屏幕并让它显示为现场?

请注意,发送到状态屏幕功能的整数值表示完成百分比。 Thread.Sleep只是为了查看更新是否/何时发生。

请注意,这不是重新绘图问题。当进度百分比传递到自定义进度条

时,我会调用Invalidate

2 个答案:

答案 0 :(得分:2)

您无法从其他线程更新控件。

正确的方法 - 将BackgroundWorker用于您的目的。 另一种方式(几乎正确的方式) - 使用Control.Invoke方法。 还有一个几乎正确的方法 - 使用SynchronizationContext。

但是你可以选择一个黑暗的力量并使用CheckForIllegalCrossThreadCalls - Control类的静态属性并将其设置为false。

答案 1 :(得分:1)

由于您的进度条位于UI /主线程上,因此您的线程无法修改它而不会导致交叉线程引用异常。您应该调用主线程的操作。

示例:

// in your thread
this.Invoke((MethodInvoker)delegate {
    statusScreen.SetProgressPercentage(value); // runs on main thread
});