Multithreading and ProgressBar
Need to make an multithreading application, which performs some activities and shows progress of all work in ProgressBar. Here is the code. Only thread named "thread - 0" makes all work. I need to distribute work between all threads.
public partial class Form1 : Form
{
const float maxWorkedValue = 10;
const int threadsCount = 5;
float totalProgress;
int threadSleepTime = 1;
object locker = new object();
开发者_运维知识库 List<Thread> threads = new List<Thread>();
public Form1()
{
InitializeComponent();
prBar.Maximum = (int)maxWorkedValue;
prBar.Step = 1;
for (int i = 0; i < threadsCount; i++)
{
threads.Add(new Thread(BeginCalculate) { Name = "Thread - " + i.ToString() });
threads[i].Start();
}
}
void BeginCalculate()
{
for (int i = 0; i < maxWorkedValue; i++)
{
lock (locker)
{
float currentProgress = CalculateLongTask(i);
Update((currentProgress / maxWorkedValue) * 100, Thread.CurrentThread.Name);
Thread.Sleep(threadSleepTime);
}
}
}
float CalculateLongTask(int value)
{
for (int i=0; i<value;i++)
Thread.Sleep(threadSleepTime);
return totalProgress++;
}
void Update(float i, string threadName)
{
if (InvokeRequired)
{
BeginInvoke(new Action<float, string>(Update), new object[] { i, threadName });
return;
}
label1.Text = threadName;
prBar.Value = (int)i;
}
}
UPDATE2: I've updated the code above. But it not resolved the problem. How to synchronize the variable "i" between different threads? An exception (progressbar.Max) is thrown. Why?
for (int i = 0; i < maxWorkedValue; i++)
{
lock (locker)
{
float currentProgress = CalculateLongTask(i);
Update((currentProgress / maxWorkedValue) * 100, Thread.CurrentThread.Name);
Thread.Sleep(15);
}
}
EDIT:
If I understood you correctly you want to execute a loop (i.e.for (int i = 0; i < maxWorkedValue; i++)
) concurrently among many threads.
This is extremely easier to accomplish using the Parallel extensions 1.
Here's your modified code:
public partial class Form1 : Form
{
const float maxWorkedValue = 100;
const int threadCount = 5;
float maxWorkedValue2 = 1;
Thread thread;
public Form1()
{
InitializeComponent();
prBar.Maximum = (int)maxWorkedValue;
prBar.Step = 1;
thread = new Thread(BeginCalculate) { Name = "Father thread" };
thread.Start();
}
void BeginCalculate()
{
Parallel.For(0, (int)maxWorkedValue,
(i) =>
{
float currentProgress = CalculateLongTask(i);
// here we are (probably) in a thread child
//of "Father thread" so let's use ManagedThreadId instead of the name...
Update((currentProgress / maxWorkedValue) * 100, Thread.CurrentThread.ManagedThreadId.ToString());
Thread.Sleep(2);
return;
});
}
float CalculateLongTask(int value)
{
for (int i = 0; i < value; i++)
Thread.Sleep(15);
return maxWorkedValue2++;
}
void Update(float i, string threadName)
{
if (InvokeRequired)
{
BeginInvoke(new Action<float, string>(Update), new object[] { i, threadName });
return;
}
label1.Text = threadName;
prBar.Value = Math.Min((int)i, 100);
}
}
1
If you're using .NET 4.0 Parallel extensions comes with the framework.
If you're using .NET 3.5, look at this Q&A to know how to use it.
Mostly, your locking scheme is broken:
void BeginCalculate() // main thread method
{
lock (locker)
{
.... // 1 thread at a time
}
}
All threads are run in sequence, you're not really multi-threading.
I can't comment on the rest except to say it doesn't look like something you should use for real.
You should probably outline what you really need to do, It won't be Sleep().
精彩评论