0

我有一个带有自定义进度条的自定义表单,在主类(主线程)中生成。然后我生成一个线程并向它发送一个 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.Sleep 只是为了查看更新是否/何时发生。

请注意,这不是重绘问题。当进度百分比传递到自定义进度条时,我调用 Invalidate

4

2 回答 2

2

您不能从另一个线程更新控件。

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

但是您可以选择权力的阴暗面并使用 CheckForIllegalCrossThreadCalls - Control 类的静态属性并将其设置为 false。

于 2013-05-02T20:30:55.137 回答
1

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

例子:

// in your thread
this.Invoke((MethodInvoker)delegate {
    statusScreen.SetProgressPercentage(value); // runs on main thread
});
于 2013-05-02T20:25:37.390 回答