如何在窗体关闭时停止用户控件上的线程

时间:2011-04-28 18:35:14

标签: c# winforms multithreading user-controls

我有一个用户控件,其中包含以下代码:

private Thread updateProgress;
private void FileUploadingScreen_Load(object sender, EventArgs e)
{
    updateProgress = new Thread(UpdateProgressBar);
    updateProgress.Start();
}
private bool run = true;
private void UpdateProgressBar()
{
    while (run)
    {
        Thread.Sleep(100);
        if(run)
        {
           progressBar1.Invoke(new Action(() =>
           {
               if (progressBar1.Value >= 100)
               {
                    progressBar1.Value = 1;
                    progressBar1.Step = 1;
               }
               progressBar1.PerformStep();
           }));
        }
    }
}

public void StopProgressBar()
{
    run = false;
}
我在父表上的

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    userControl.StopProgressBar();
}

当我通过点击X关闭表单时,我在progressBar1.Invoke行上收到以下错误。

  

Invoke or BeginInvoke cannot be called on a control until the window handle has been created.

我认为在form_closing事件中设置run为false会阻止这种情况发生。我怎样才能解决这个问题?我的主要目标是拥有一个继续前进的进度条,以显示某些事情仍在发生。有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

您可以使用此

public void StopProgressBar()
{
    updateProgress.Abort();
}

我认为这是一种有效的方法。应用程序将继续运行,因为有一个线程仍处于活动状态。中止该线程将其全部关闭。

但是,每次从UserControl外部手动调用此操作都很繁琐。您最好让用户控制自我管理并自行清理

根据这个discussion,在Designer.cs中更改控件的Dispose方法是安全的,VS应该尊重这些更改而不是覆盖它们。

protected override void Dispose(bool disposing)
{
    if (disposing && (components != null))
    {
        components.Dispose();
    }
    //Special handling of started thread
    if (disposing && updateProgress.IsAlive)
    {
        updateProgress.Abort();
    }
    base.Dispose(disposing);
}

这样,您的父表单不必显式调用StopProgressBar。

答案 1 :(得分:0)

尝试

public void StopProgressBar()
{
    run = false;
    updateProgress.Join();
}

问题是你假设只要你将'run'设置为false,线程就会停止。发生的事情是Windows在您的线程仍在执行时继续处理窗口。该解决方案的作用是阻塞,直到线程完成执行。