Problem with faking a progress bar / threading.

C

CCLeasing

For an application I'm creating I want to create a 'fake' progress
bar.
By fake I mean a progress bar that looks like it's doing something but
actually isn't.

I know philosophically this isn't sound. But my little app is a 'fake'
app and is designed to look like another - hence this seeming crazy
situation of needing to fake a progess bar.

PROBLEM.
I can not figure out how to delay the execution of my code to pause
between updates of the progress bar value, I had thought i could do
something like this.

progressbar1.value = 10;
wait for 20 seconds....
progressbar1.value=50;
wait for 10 seconds....
progressbar1.value=90;

etc... The problem I have is that the only method i've managed to find
of pausing code execution is the thread.sleep method. However this
causes the form not to be displayed, from what i've gathered this is
because the part of the code that actually paints the form is
disrupted by the call to make the thread sleep.

My Attempted Solution.

I tried to create a new thread and put the code that deals with the
progress bar in that thread. This created an error about cross thread
referencing. I then disabled cross thread referencing using
Control.CheckForIllegalCrossThreadCalls = false; but it's still not
working.

Any ideas how to fix this.
Here is what I have so far.
=====================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Stealth
{
public partial class Form3 : Form
{

public Form3()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;

}
private void myStartingMethod()
{
//change value to 20.
progressBar1.Value = 20;
//pause
System.Threading.Thread.Sleep(5000);
//change value to 90.
progressBar1.Value = 90;


}
private void Form3_Load(object sender, EventArgs e)
{

InitializeComponent();

System.Threading.Thread myThread;
myThread = new System.Threading.Thread(new
System.Threading.ThreadStart(myStartingMethod));


myThread.Start();

}


}
}
=================
TIA.
 
M

Matt Lacey

For an application I'm creating I want to create a 'fake' progress
bar.
By fake I mean a progress bar that looks like it's doing something but
actually isn't.

I know philosophically this isn't sound. But my little app is a 'fake'
app and is designed to look like another - hence this seeming crazy
situation of needing to fake a progess bar.

PROBLEM.
I can not figure out how to delay the execution of my code to pause
between updates of the progress bar value, I had thought i could do
something like this.

progressbar1.value = 10;
wait for 20 seconds....
progressbar1.value=50;
wait for 10 seconds....
progressbar1.value=90;

etc... The problem I have is that the only method i've managed to find
of pausing code execution is the thread.sleep method. However this
causes the form not to be displayed, from what i've gathered this is
because the part of the code that actually paints the form is
disrupted by the call to make the thread sleep.

My Attempted Solution.

I tried to create a new thread and put the code that deals with the
progress bar in that thread. This created an error about cross thread
referencing. I then disabled cross thread referencing using
Control.CheckForIllegalCrossThreadCalls = false; but it's still not
working.

Any ideas how to fix this.
Here is what I have so far.
=====================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Stealth
{
public partial class Form3 : Form
{

public Form3()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;

}
private void myStartingMethod()
{
//change value to 20.
progressBar1.Value = 20;
//pause
System.Threading.Thread.Sleep(5000);
//change value to 90.
progressBar1.Value = 90;

}
private void Form3_Load(object sender, EventArgs e)
{

InitializeComponent();

System.Threading.Thread myThread;
myThread = new System.Threading.Thread(new
System.Threading.ThreadStart(myStartingMethod));

myThread.Start();

}

}}

=================
TIA.

It doesn't solve your threading problem, but using a timer to
increment the progress bar will have the same desired effect:
add a progressbar, button & timer to your form and try the following
code to see how it might work:

private void timer1_Tick(object sender, System.EventArgs e)
{
if (progressBar1.Value < 100)
{
progressBar1.Value = progressBar1.Value + 5;
}
}

private void button1_Click(object sender, System.EventArgs e)
{
progressBar1.Value = 0;
}

private void Form1_Load(object sender, System.EventArgs e)
{
timer1.Enabled = true;
}

Adjust the timer interval and the amount the progress bar increments
as needed.
 
W

william.w.oneill

In your myStartingMethod method, look at using progressBar1.Invoke()
or BeginInvoke(). These methods provide the functionality you need.
 
B

Ben Schwehn

For an application I'm creating I want to create a 'fake' progress bar.
By fake I mean a progress bar that looks like it's doing something but
actually isn't.

I know philosophically this isn't sound. But my little app is a 'fake'
app and is designed to look like another - hence this seeming crazy
situation of needing to fake a progess bar.

Hello CCLeasing,

A 'fake' progress bar is a perfectly reasonalble solution in situations
where you want to give the user feedback that you're still doing
something (and haven't crashed), but can't calculate how much longer it's
going to take.

PROBLEM.
I can not figure out how to delay the execution of my code to pause
between updates of the progress bar value, I had thought i could do
something like this.

progressbar1.value = 10;
wait for 20 seconds....
progressbar1.value=50;
wait for 10 seconds....
progressbar1.value=90;

This doesn't work, because you're blocking the main UI thread, so the UI
can't update anymore. Read up on multithreading in windows forms if you
don't understand why this happens. Start for exampl here http://
msdn2.microsoft.com/en-us/library/ms951089.aspx

I tried to create a new thread and put the code that deals with the
progress bar in that thread. This created an error about cross thread
referencing. I then disabled cross thread referencing using
Control.CheckForIllegalCrossThreadCalls = false; but it's still not
working.

You really shouldn't do that. It can cause difficult to debug problems.
The cross thread warning is there for a reason after all.
Any ideas how to fix this.
Here is what I have so far.

The quickest and easiest solution is probalby using the
System.Windows.Forms.Timer class. Update the progress bar in the Timer's
Tick event.

That way you don't have to deal with multithreading issues (the tick
eventhandler will run in the main UI-Thread)

Ben
 
C

Chris Shepherd

CCLeasing said:
For an application I'm creating I want to create a 'fake' progress
bar.
By fake I mean a progress bar that looks like it's doing something but
actually isn't.

I know philosophically this isn't sound. But my little app is a 'fake'
app and is designed to look like another - hence this seeming crazy
situation of needing to fake a progess bar.

Use a BackgroundWorker and set it to report its progress. This is what
it is designed for.

Chris.
 
A

Arnshea

For an application I'm creating I want to create a 'fake' progress
bar.
By fake I mean a progress bar that looks like it's doing something but
actually isn't.

I know philosophically this isn't sound. But my little app is a 'fake'
app and is designed to look like another - hence this seeming crazy
situation of needing to fake a progess bar.

PROBLEM.
I can not figure out how to delay the execution of my code to pause
between updates of the progress bar value, I had thought i could do
something like this.

progressbar1.value = 10;
wait for 20 seconds....
progressbar1.value=50;
wait for 10 seconds....
progressbar1.value=90;

etc... The problem I have is that the only method i've managed to find
of pausing code execution is the thread.sleep method. However this
causes the form not to be displayed, from what i've gathered this is
because the part of the code that actually paints the form is
disrupted by the call to make the thread sleep.

My Attempted Solution.

I tried to create a new thread and put the code that deals with the
progress bar in that thread. This created an error about cross thread
referencing. I then disabled cross thread referencing using
Control.CheckForIllegalCrossThreadCalls = false; but it's still not
working.

Any ideas how to fix this.
Here is what I have so far.
=====================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Stealth
{
public partial class Form3 : Form
{

public Form3()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;

}
private void myStartingMethod()
{
//change value to 20.
progressBar1.Value = 20;
//pause
System.Threading.Thread.Sleep(5000);
//change value to 90.
progressBar1.Value = 90;

}
private void Form3_Load(object sender, EventArgs e)
{

InitializeComponent();

System.Threading.Thread myThread;
myThread = new System.Threading.Thread(new
System.Threading.ThreadStart(myStartingMethod));

myThread.Start();

}

}}

=================
TIA.

Calls that update a UI object have to be marshaled onto the UI
thread. I find the following pattern helpful:

void MethodThatUpdatesUI()
{
if (InvokeRequired)
Invoke(new MethodInvoker(MethodThatUpdatesUI));
else
{
// update whatever ui controls
}
}

The only downside is the proliferation of one-off delegates if you
need to pass data into/out of the method.
 
P

Peter Duniho

Arnshea said:
Calls that update a UI object have to be marshaled onto the UI
thread. I find the following pattern helpful:

void MethodThatUpdatesUI()
{
if (InvokeRequired)
Invoke(new MethodInvoker(MethodThatUpdatesUI));
else
{
// update whatever ui controls
}
}

The only downside is the proliferation of one-off delegates if you
need to pass data into/out of the method.

That latter issue is not a problem at all with the use of anonymous methods.

However, I don't like the general pattern myself, because of the
proliferation of methods that do two completely different things
depending on what thread they are on.

I prefer to either have a single method always used regardless of thread
and which always calls Invoke(), or to simply have the thread be aware
of whether it needs to call Invoke() itself.

That said, IMHO Matt's answer was the best in this situation, since no
actual work is being done in a background thread. All that's really
necessary is to update the progress bar periodically, and a Timer is a
fine way to do that without introducing any of the cross-thread issues
while still preserving a responsive UI.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top