Updating progress bar from a threadpool c#
I have trying to process some data using multithreading where I am using threadpool to generate threads equal to the number of cores(Limited to .NET 2.0 to 3.5 so cant use TPL).
All my threads execute the same function operating in different parts of my data.
My problem is I am unable to update the progress bar from the threads of the threadpool. Found 开发者_C百科solutions such as invoke and Background worker but could not really understand how to use them please help me out how to use them.
my code looks like
private static float[] inpdat=new float[1000];//The input array to process
//The spawned threads
public void dowork(object o)
{
int np = (int)o;
for(int i=np;i<inpdat.length;i=i+Environment.ProcessorCount)
{
//do some processing
if(np==0)
{
//update progress bar here
}
}
}
//The main thread
for (int npou = 0; npou < numproc; npou++)
{
resetEvents[npou] = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(new WaitCallback(dowork), npou);
PetrelLogger.InfoOutputWindow("manual reset event set");
}
Speed is of paramount importance to me so would be very helpful if the cross thread calling takes up minimum time. Thanks
Here is an example:
ThreadPool.QueueUserWorkItem(new WaitCallback(o =>
{
// worker method implementation
.....
progressBar1.Invoke(new MethodInvoker(() => progressBar1.Value = 20));
}));
There is a little you can do with updating user controls, in your case Progress bar. Add your form as the input parameter, or add some callback interface for the results, that your form will implement:
interface IMyCallback
{
void Progress(int progress);
}
In form implementation add following code:
void Progress(int Progress)
{
if(this.InvokeRequired)
{
this.BeginInvoke(new ParametrizedThreadStart(Inv_Progress), Progress);
}
else
{
Inv_Progress(Progress);
}
}
void Inv_Progress(object obj)
{
int progress = obj as int;
// do your update progress bar work here
}
Now you can do following:
public void dowork(object o)
{
int np = (int)o;
for(int i=np;i<inpdat.length;i=i+Environment.ProcessorCount)
{
//do some processing
if(np==0)
{
myCallback.Progress(0);
}
}
}
A standard invoke is probably easiest, and you can use an anonymous delegate to make it cleaner.
int n = 5;
myProgressBar.Invoke(
delegate
{
myProgressBar.Value = n;
}
);
Keep in mind that in certain scenarios (e.g. looped use of this delegate from within one thread) you may need to declare a delegate and pass the value into it as a parameter. If you don't, you can get strange behaviour with locals. This is the case for use of anonymous methods and the Action
class, too.
精彩评论