I have a user control with the following code in it:
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;
}
on the parent form I have :
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
userControl.StopProgressBar();
}
when I close the form by clicking the X I'm getting the following error on the progressBar1.Invoke
line.
Invoke or BeginInvoke 开发者_JAVA百科cannot be called on a control until the window handle has been created.
I thought setting run to false in the form_closing
event would stop this from happening. How can I fix this? My main goal is to have a progressbar that keeps moving to show that something is happening still. Is there a better way to do this?
You can use this
public void StopProgressBar()
{
updateProgress.Abort();
}
I think it's a valid approach. The application will keep running because there's a thread still active. Aborting that thread shuts it all down.
However, calling this manually every time from outside the UserControl is tedious. You're better off making your user control self-managing and clean up after itself.
As per this discussion, changing the control's Dispose method in Designer.cs is safe, VS should respect these changes and not overwrite them.
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);
}
With this, your parent form does not have to call StopProgressBar explicitly.
Try
public void StopProgressBar()
{
run = false;
updateProgress.Join();
}
The problem is that you're assuming that as soon as you set 'run' to false, the thread is going to stop. What's happening is that Windows continues disposing the window while your thread is still being executed. What this solution does is block until the thread completes execution.
精彩评论