By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,709 Members | 2,153 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,709 IT Pros & Developers. It's quick & easy.

Threading and the Progress Bar

P: n/a
I guess it's my turn to ASK a question ;)

Briefly my problem: I am developing a Windows app that has several User
Controls. On one of these controls, I am copying/processing some rather
large binary files, so have created a second thread to do the processing.
This thread is set to be the LOWEST priority. So far so good with all that.
HOWEVER, I am trying to provide some feedback to the user (the bane of our
existence!) via a progress bar. I was attempting to update the progress bar
via code in a timer's event. When I have the timer on the the same control
as the progress bar, the application reacts the same was as it did prior to
starting the second thread, that is, it locks up the UI until the copying is
complete, AND the progress bar never gets updated.

I have a Main user control that controls the activities of the other
controls, and that has a timer on it, so I thought I would use that timer
event instead. Same reaction. UI locks up until the copy function is
complete, and the progress bar never gets updated.

Any thoughts on how I can approach this? Suggestions on what I'm doing
wrong etc?

TIA

WhiteWizard
aka Gandalf
MCSD.NET, MCAD, MCT
Sep 6 '06 #1
Share this Question
Share on Google+
8 Replies


P: n/a
First, you should not be setting the priority of the thread. Generally,
this is a bad idea. See the following blog entry for more information:

http://www.codinghorror.com/blog/archives/000671.html

As for updating the progress bar, why are you using a timer to indicate
when the progress bar should be updated? Why not send notifications from
your worker thread to the control with the progress bar?
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"WhiteWizard" <Wh*********@discussions.microsoft.comwrote in message
news:C9**********************************@microsof t.com...
>I guess it's my turn to ASK a question ;)

Briefly my problem: I am developing a Windows app that has several User
Controls. On one of these controls, I am copying/processing some rather
large binary files, so have created a second thread to do the processing.
This thread is set to be the LOWEST priority. So far so good with all
that.
HOWEVER, I am trying to provide some feedback to the user (the bane of our
existence!) via a progress bar. I was attempting to update the progress
bar
via code in a timer's event. When I have the timer on the the same
control
as the progress bar, the application reacts the same was as it did prior
to
starting the second thread, that is, it locks up the UI until the copying
is
complete, AND the progress bar never gets updated.

I have a Main user control that controls the activities of the other
controls, and that has a timer on it, so I thought I would use that timer
event instead. Same reaction. UI locks up until the copy function is
complete, and the progress bar never gets updated.

Any thoughts on how I can approach this? Suggestions on what I'm doing
wrong etc?

TIA

WhiteWizard
aka Gandalf
MCSD.NET, MCAD, MCT

Sep 6 '06 #2

P: n/a
Nicholas,

Thanks for the input, I'm going to try it without the timer.

As for setting the thread priorities, I also generally avoid them like the
plague, however in this case we really do need to do it.

We are getting information from an onboard computer on the aircraft in
"real" time (not really, but close enough for gov't work! ;). This process
(and one other) cannot impede the processing of that data. We really don't
care how long it takes, as long as it doesn't inhibit the main thread at all.

Thanks for the response.

WhiteWizard
aka Gandalf
MCSD.NET, MCAD, MCT
"Nicholas Paldino [.NET/C# MVP]" wrote:
First, you should not be setting the priority of the thread. Generally,
this is a bad idea. See the following blog entry for more information:

http://www.codinghorror.com/blog/archives/000671.html

As for updating the progress bar, why are you using a timer to indicate
when the progress bar should be updated? Why not send notifications from
your worker thread to the control with the progress bar?
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"WhiteWizard" <Wh*********@discussions.microsoft.comwrote in message
news:C9**********************************@microsof t.com...
I guess it's my turn to ASK a question ;)

Briefly my problem: I am developing a Windows app that has several User
Controls. On one of these controls, I am copying/processing some rather
large binary files, so have created a second thread to do the processing.
This thread is set to be the LOWEST priority. So far so good with all
that.
HOWEVER, I am trying to provide some feedback to the user (the bane of our
existence!) via a progress bar. I was attempting to update the progress
bar
via code in a timer's event. When I have the timer on the the same
control
as the progress bar, the application reacts the same was as it did prior
to
starting the second thread, that is, it locks up the UI until the copying
is
complete, AND the progress bar never gets updated.

I have a Main user control that controls the activities of the other
controls, and that has a timer on it, so I thought I would use that timer
event instead. Same reaction. UI locks up until the copy function is
complete, and the progress bar never gets updated.

Any thoughts on how I can approach this? Suggestions on what I'm doing
wrong etc?

TIA

WhiteWizard
aka Gandalf
MCSD.NET, MCAD, MCT


Sep 6 '06 #3

P: n/a
Hello,
I'm new to GUI programming in C# and so I would like to ask this question
here, because it's related to the topic. I had the same (or at least a very
similar) scenario where a worker thread does some work and a progressbar
should show the user how much of the work has already been done. But as GUI
and threads don't really like to work together without problems, I would like
to know how I can interact which the progressbar from the worker thread?

greetings

Florian

"Nicholas Paldino [.NET/C# MVP]" wrote:
First, you should not be setting the priority of the thread. Generally,
this is a bad idea. See the following blog entry for more information:

http://www.codinghorror.com/blog/archives/000671.html

As for updating the progress bar, why are you using a timer to indicate
when the progress bar should be updated? Why not send notifications from
your worker thread to the control with the progress bar?
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"WhiteWizard" <Wh*********@discussions.microsoft.comwrote in message
news:C9**********************************@microsof t.com...
I guess it's my turn to ASK a question ;)

Briefly my problem: I am developing a Windows app that has several User
Controls. On one of these controls, I am copying/processing some rather
large binary files, so have created a second thread to do the processing.
This thread is set to be the LOWEST priority. So far so good with all
that.
HOWEVER, I am trying to provide some feedback to the user (the bane of our
existence!) via a progress bar. I was attempting to update the progress
bar
via code in a timer's event. When I have the timer on the the same
control
as the progress bar, the application reacts the same was as it did prior
to
starting the second thread, that is, it locks up the UI until the copying
is
complete, AND the progress bar never gets updated.

I have a Main user control that controls the activities of the other
controls, and that has a timer on it, so I thought I would use that timer
event instead. Same reaction. UI locks up until the copy function is
complete, and the progress bar never gets updated.

Any thoughts on how I can approach this? Suggestions on what I'm doing
wrong etc?

TIA

WhiteWizard
aka Gandalf
MCSD.NET, MCAD, MCT


Sep 6 '06 #4

P: n/a
Here's what I came up with, and it works just great. THANKS NICHOLAS!

private void StartCopyThread()
{
copyRMMDataThread = new Thread(new ThreadStart(ProcessCopyRequest));
copyRMMDataThread.Name = "copyRMMDataThread";
copyRMMDataThread.Priority = System.Threading.ThreadPriority.Lowest;
copyRMMDataThread.Start();
}

private void ProcessCopyRequest()
{
// some initial processing

pbFileCopy.Value = 0;
pbFileCopy.Refresh();

// First we create the directory on the RMM that we are going to copy the
files to
bool dirCreated = CreateRMMCopyDirectories();
if (dirCreated)
{
try
{
// If the directories were created, we create the files...

// ...then read the trend file and process it
string filename = strAMCDirectory + @"\trend1.bin";
Stream Trend = myFlightData.ReadFlightFile(filename);
BinaryReader BinaryTrend = new BinaryReader(Trend);

while (true)
{
int NumberOfBytes = BinaryTrend.ReadInt32();
if (NumberOfBytes != 0)
{
byte[] binarySecond = BinaryTrend.ReadBytes(NumberOfBytes);
EDSCommon.TrendDataType second = ParseBinarySecond(binarySecond);
// Update the progress bar
pbFileCopy.Value = Convert.ToInt32((Trend.Position / rmmTrendSize)
* 100);
pbFileCopy.Refresh();

// continue processing
}
}

HTH

WhiteWizard
aka Gandalf
MCSD.NET, MCAD, MCT
"Stampede" wrote:
Hello,
I'm new to GUI programming in C# and so I would like to ask this question
here, because it's related to the topic. I had the same (or at least a very
similar) scenario where a worker thread does some work and a progressbar
should show the user how much of the work has already been done. But as GUI
and threads don't really like to work together without problems, I would like
to know how I can interact which the progressbar from the worker thread?

greetings

Florian

"Nicholas Paldino [.NET/C# MVP]" wrote:
First, you should not be setting the priority of the thread. Generally,
this is a bad idea. See the following blog entry for more information:

http://www.codinghorror.com/blog/archives/000671.html

As for updating the progress bar, why are you using a timer to indicate
when the progress bar should be updated? Why not send notifications from
your worker thread to the control with the progress bar?
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"WhiteWizard" <Wh*********@discussions.microsoft.comwrote in message
news:C9**********************************@microsof t.com...
>I guess it's my turn to ASK a question ;)
>
Briefly my problem: I am developing a Windows app that has several User
Controls. On one of these controls, I am copying/processing some rather
large binary files, so have created a second thread to do the processing.
This thread is set to be the LOWEST priority. So far so good with all
that.
HOWEVER, I am trying to provide some feedback to the user (the bane of our
existence!) via a progress bar. I was attempting to update the progress
bar
via code in a timer's event. When I have the timer on the the same
control
as the progress bar, the application reacts the same was as it did prior
to
starting the second thread, that is, it locks up the UI until the copying
is
complete, AND the progress bar never gets updated.
>
I have a Main user control that controls the activities of the other
controls, and that has a timer on it, so I thought I would use that timer
event instead. Same reaction. UI locks up until the copy function is
complete, and the progress bar never gets updated.
>
Any thoughts on how I can approach this? Suggestions on what I'm doing
wrong etc?
>
TIA
>
WhiteWizard
aka Gandalf
MCSD.NET, MCAD, MCT
Sep 6 '06 #5

P: n/a
Woah, you need to change this code big time.

What I would do is before you start the new thread, set the Value
property of your progress bar to zero.

Then, define the following delegate:

private delegate void SetProgressBarValueDelegate(int value);

And then define the following method:

private void SetProgressBarValue(int value)
{
// Set the value.
pbFileCopy.Value = value;
}

Then, wherever you have a call to "pbFileCopy.Value = ?" in your
ProcessCopyRequest method, change it to:

this.Invoke(new SetProgressBarValueDelegate(SetProgressBarValue), new
object[]{ <value});

The reason you need to do this is that you need to make calls to update
the UI on the UI thread. The call to Invoke takes a delegate and executes
it on the UI thread.

If you are using .NET 2.0, you don't even need to declare the delegate
or the method, you could do this:

Action<intdel = delegate(int value) { pbFileCopy.Value = value; };
this.Invoke(del, new object[]{ <value});

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"WhiteWizard" <Wh*********@discussions.microsoft.comwrote in message
news:DB**********************************@microsof t.com...
Here's what I came up with, and it works just great. THANKS NICHOLAS!

private void StartCopyThread()
{
copyRMMDataThread = new Thread(new ThreadStart(ProcessCopyRequest));
copyRMMDataThread.Name = "copyRMMDataThread";
copyRMMDataThread.Priority = System.Threading.ThreadPriority.Lowest;
copyRMMDataThread.Start();
}

private void ProcessCopyRequest()
{
// some initial processing

pbFileCopy.Value = 0;
pbFileCopy.Refresh();

// First we create the directory on the RMM that we are going to copy the
files to
bool dirCreated = CreateRMMCopyDirectories();
if (dirCreated)
{
try
{
// If the directories were created, we create the files...

// ...then read the trend file and process it
string filename = strAMCDirectory + @"\trend1.bin";
Stream Trend = myFlightData.ReadFlightFile(filename);
BinaryReader BinaryTrend = new BinaryReader(Trend);

while (true)
{
int NumberOfBytes = BinaryTrend.ReadInt32();
if (NumberOfBytes != 0)
{
byte[] binarySecond = BinaryTrend.ReadBytes(NumberOfBytes);
EDSCommon.TrendDataType second = ParseBinarySecond(binarySecond);
// Update the progress bar
pbFileCopy.Value = Convert.ToInt32((Trend.Position / rmmTrendSize)
* 100);
pbFileCopy.Refresh();

// continue processing
}
}

HTH

WhiteWizard
aka Gandalf
MCSD.NET, MCAD, MCT
"Stampede" wrote:
>Hello,
I'm new to GUI programming in C# and so I would like to ask this question
here, because it's related to the topic. I had the same (or at least a
very
similar) scenario where a worker thread does some work and a progressbar
should show the user how much of the work has already been done. But as
GUI
and threads don't really like to work together without problems, I would
like
to know how I can interact which the progressbar from the worker thread?

greetings

Florian

"Nicholas Paldino [.NET/C# MVP]" wrote:
First, you should not be setting the priority of the thread.
Generally,
this is a bad idea. See the following blog entry for more information:

http://www.codinghorror.com/blog/archives/000671.html

As for updating the progress bar, why are you using a timer to
indicate
when the progress bar should be updated? Why not send notifications
from
your worker thread to the control with the progress bar?
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"WhiteWizard" <Wh*********@discussions.microsoft.comwrote in message
news:C9**********************************@microsof t.com...
I guess it's my turn to ASK a question ;)

Briefly my problem: I am developing a Windows app that has several
User
Controls. On one of these controls, I am copying/processing some
rather
large binary files, so have created a second thread to do the
processing.
This thread is set to be the LOWEST priority. So far so good with
all
that.
HOWEVER, I am trying to provide some feedback to the user (the bane
of our
existence!) via a progress bar. I was attempting to update the
progress
bar
via code in a timer's event. When I have the timer on the the same
control
as the progress bar, the application reacts the same was as it did
prior
to
starting the second thread, that is, it locks up the UI until the
copying
is
complete, AND the progress bar never gets updated.

I have a Main user control that controls the activities of the other
controls, and that has a timer on it, so I thought I would use that
timer
event instead. Same reaction. UI locks up until the copy function
is
complete, and the progress bar never gets updated.

Any thoughts on how I can approach this? Suggestions on what I'm
doing
wrong etc?

TIA

WhiteWizard
aka Gandalf
MCSD.NET, MCAD, MCT

Sep 6 '06 #6

P: n/a
With 2.0 it can be really simple.
private void button4_Click(object sender, EventArgs e)
{
int num = 0;
new Thread(
delegate()
{
while (num < 100)
{
// Do work.
num++;
Thread.Sleep(100);

// Update progress bar.
this.Invoke(
(MethodInvoker)delegate()
{
this.progressBar1.Value = num;
});
}
}).Start();
}

--
William Stacey [MVP]

"WhiteWizard" <Wh*********@discussions.microsoft.comwrote in message
news:C9**********************************@microsof t.com...
|I guess it's my turn to ASK a question ;)
|
| Briefly my problem: I am developing a Windows app that has several User
| Controls. On one of these controls, I am copying/processing some rather
| large binary files, so have created a second thread to do the processing.
| This thread is set to be the LOWEST priority. So far so good with all
that.
| HOWEVER, I am trying to provide some feedback to the user (the bane of our
| existence!) via a progress bar. I was attempting to update the progress
bar
| via code in a timer's event. When I have the timer on the the same
control
| as the progress bar, the application reacts the same was as it did prior
to
| starting the second thread, that is, it locks up the UI until the copying
is
| complete, AND the progress bar never gets updated.
|
| I have a Main user control that controls the activities of the other
| controls, and that has a timer on it, so I thought I would use that timer
| event instead. Same reaction. UI locks up until the copy function is
| complete, and the progress bar never gets updated.
|
| Any thoughts on how I can approach this? Suggestions on what I'm doing
| wrong etc?
|
| TIA
|
| WhiteWizard
| aka Gandalf
| MCSD.NET, MCAD, MCT
Sep 6 '06 #7

P: n/a
Just a suggestion: the BackgroundWorker class comes in very handy when
doing resources-intensive stuff. I use it quite a lot and am very happy
with it.
The advantages:
1. the load is put on a seperate thread so your GUI doesn't suffer
the consequences
2. you can split your code easily into a processing part and GUI
updating parts
This would be an example:

private ProgressBar bar;
private BackgroundWorker bgWorker;

// Initialize your progressbar
bar = new ProgressBar();
bar.Value = 0;
bar.Maximum = 100;

// Initialize your backgroundworker
bgWorker = new BackgroundWorker()
bgWorker.WorkerReportsProgress = true;
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(bgWorker_RunWorkerC ompleted);
bgWorker.ProgressChanged += new
ProgressChangedEventHandler(bgWorker_ProgressChang ed);
// Call to time and resources consuming code
// asynchronously
bgWorker.RunWorkerAsync();

private void bgWorker_Dowork (object sender, DoWorkEventArgs e)
{
// Her comes your actual heavy code.
// Keep threads separated, so no calls to GUI should be made.
// Instead, use the ReportProgress(int myValue) method
for (int i = 0; i < 100; i++)
{
bgWorker.ReportProgress(i);
}
}

private void bgWorker_ProgressChanged (object sender,
ProgressChangedEventArgs e)
{
// Here you can take care of the GUI
// Update your progressbar
bar.Value = e.ProgressPercentage;
}

private void bgWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
// Here you can take care of all GUI things that need resetting
// and stuff like that
bar.Value = 0;
}

Sep 7 '06 #8

P: n/a
It is fine to use. Myself I find it easier to use delegates and Invoke as
shown. Then I am not dealing with another class and its api, and I get a
more inline feel.

--
William Stacey [MVP]

<jo*****@yamagata-europe.comwrote in message
news:11**********************@i42g2000cwa.googlegr oups.com...
| Just a suggestion: the BackgroundWorker class comes in very handy when
| doing resources-intensive stuff. I use it quite a lot and am very happy
| with it.
| The advantages:
| 1. the load is put on a seperate thread so your GUI doesn't suffer
| the consequences
| 2. you can split your code easily into a processing part and GUI
| updating parts
| This would be an example:
|
| private ProgressBar bar;
| private BackgroundWorker bgWorker;
|
| // Initialize your progressbar
| bar = new ProgressBar();
| bar.Value = 0;
| bar.Maximum = 100;
|
| // Initialize your backgroundworker
| bgWorker = new BackgroundWorker()
| bgWorker.WorkerReportsProgress = true;
| bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
| bgWorker.RunWorkerCompleted += new
| RunWorkerCompletedEventHandler(bgWorker_RunWorkerC ompleted);
| bgWorker.ProgressChanged += new
| ProgressChangedEventHandler(bgWorker_ProgressChang ed);
|
|
| // Call to time and resources consuming code
| // asynchronously
| bgWorker.RunWorkerAsync();
|
| private void bgWorker_Dowork (object sender, DoWorkEventArgs e)
| {
| // Her comes your actual heavy code.
| // Keep threads separated, so no calls to GUI should be made.
| // Instead, use the ReportProgress(int myValue) method
| for (int i = 0; i < 100; i++)
| {
| bgWorker.ReportProgress(i);
| }
| }
|
| private void bgWorker_ProgressChanged (object sender,
| ProgressChangedEventArgs e)
| {
| // Here you can take care of the GUI
| // Update your progressbar
| bar.Value = e.ProgressPercentage;
| }
|
| private void bgWorker_RunWorkerCompleted(object sender,
| RunWorkerCompletedEventArgs e)
| {
| // Here you can take care of all GUI things that need resetting
| // and stuff like that
| bar.Value = 0;
| }
|
Sep 7 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.