我有一个用户控件,其中包含以下代码:
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会阻止这种情况发生。我怎样才能解决这个问题?我的主要目标是拥有一个继续前进的进度条,以显示某些事情仍在发生。有更好的方法吗?
答案 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在您的线程仍在执行时继续处理窗口。该解决方案的作用是阻塞,直到线程完成执行。