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

线程未更新进度条控件-C#,c#,multithreading,winforms,progress-bar,progress,C#,Multithreading,Winforms,Progress Bar,Progress,我有一个带有自定义进度条的自定义表单,它是在主类(主线程)中生成的。然后生成一个线程,并向其发送一个ThreadStart函数。此线程启动函数应更新自定义控件中的进度条,但不会: class MyClass { ...... //Custom form with progress bar public CustomFormWithProgressBar statusScreen = new CustomFormWithProgressBar(0); //thread to use private

我有一个带有自定义进度条的自定义表单,它是在主类(主线程)中生成的。然后生成一个线程,并向其发送一个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();
}
class-MyClass
{
......
//带有进度条的自定义表单
公共CustomFormWithProgressBar状态屏幕=新CustomFormWithProgressBar(0);
//要使用的线程
私有线程读取;
.....
//链接到按钮以触发更新过程。
空按钮压力(……)
{
//创建一个子线程来运行工作并处理进度条的UI更新
myThread=新线程(新线程开始(线程函数));
myThread.Start();
}
.....
//线程运行时调用的函数
公共函数()
{
//MyThreadClass myThreadClassObject=新的MyThreadClass(此);
//myThreadClassObject.Run();
statusScreen.ShowStatusScreen();
对于(int i=0;i<100;i++)
{
statusScreen.SetProgressPercentage(i);
睡眠(20);
}
statusScreen.CloseStatusScreen();
}
现在,我的statusScreen表单只是坐在那里,什么也不做。没有更新发生。但我已经确认子线程确实已创建,并且当我在ThreadFunction中时,我正在新线程上运行。这是通过visual studio中的线程窗口确定的

为什么我对状态屏幕的进度百分比的更新没有显示?如何让我的更新将新值推送到进度屏幕并使其实时显示

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


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

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

例如:

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

由于进度条位于UI/主线程上,因此线程无法在不导致跨线程引用异常的情况下对其进行修改。您应该调用主线程的操作

例如:

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

不能从其他线程更新控件

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


但您可以选择power的阴暗面,使用CheckForIllegalCrossThreadCalls—Control类的静态属性并将其设置为false。

您不能从其他线程更新控件

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


但您可以选择power的黑暗面,使用CheckForIllegalCrossThreadCalls(控件类的静态属性)并将其设置为false。

我尝试了invoke和backgroundWorker,但我无法获得它。您能否在OP中给出一个应用于我的代码的示例?我将非常感激。1.您在非GUI Thread.Mo中创建进度窗口ve statusScreen.ShowStatusScreen();到ButtonPressEvent。然后在ButtonPressEvent中创建BackgroundWorker。为DoWork和Completed、ProgressChanged事件创建处理程序。请参阅MSDN上的BackgroundWorker帮助。并在Completed event中关闭状态屏幕。我尝试过调用和BackgroundWorker,但无法获得它。您能给出一个应用于我在OP中的代码的示例吗?我想非常感谢。1.在非GUI线程中创建进度窗口。移动状态屏幕。显示状态屏幕();至ButtonPressEvent。然后在ButtonPressEvent中创建BackgroundWorker。为DoWork和Completed、ProgressChanged事件创建处理程序。请参阅MSDN上的BackgroundWorker帮助。并在Completed event中关闭Status Screen。我刚刚在我的copmuter上尝试了此操作,但它很难崩溃。因此,我将重试,并让您知道发生异常是什么意思抛出?不,它只是锁定了系统并被黑屏屏蔽。难以重新启动哈维利很奇怪,我不知道添加上面的行会导致什么。这可能只是巧合。我刚刚在我的共话器上尝试了这个,它崩溃了。所以我会再试一次,让你知道你的意思,抛出了一个异常?不,它只是被锁定了系统和黑屏被屏蔽了。很难很难重新启动哈维利很奇怪,我不明白上面的代码怎么会导致这样。这可能只是巧合