Multithreading and ProgressBar - c#

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().

Related

How to get and print how many times a loop spins in a thread before it gets switched to other threads?

Instead of printing o and -, I want to print the number of o and - on the console. However, I have no idea how to get how many times a loop spins in a thread before it gets switched to other threads.
If there are events something likes OnLeaving and OnEntering on a thread, I can get the number of spins in the given time slice. Unfortunately, I have no such events.
class Program
{
public const int N = 1000;
static void Main(string[] args)
{
ThreadStart ts = DoWork;
Thread t = new Thread(ts);
t.Start();
for (int x = 0; x < N; x++)
{
Console.Write('o');
}
t.Join();
}
private static void DoWork()
{
for (int x = 0; x < N; x++)
{
Console.Write('-');
}
}
}
Could you show me how to do this scenario?
To reiterate: AbhayDixit's comment gives you a cycle counter. You just need to add a locking mechanism and reset the counters after a context switch.
I have modified your code to include a cycle counter. Note that I have increased N significantly. Otherwise, one thread will just run through its 1000 iterations at once - because you no longer have a Write() instruction to slow it down.
class Program
{
public const int N = 1000000;
private static object _l = new object();
private static int _i = 0;
private static int _j = 0;
static void Main(string[] args)
{
ThreadStart ts = DoWork;
Thread t = new Thread(ts);
t.Start();
for (int x = 0; x < N; x++)
{
lock (_l)
{
// j-thread has run?
if (_j > 0)
{
// print and reset j
Console.Write("j{0} ", _j);
_j = 0;
}
_i++;
}
}
t.Join();
// print remaining cycles
// one of the threads will have run after the other has finished and
// hence not been printed and reset.
if (_i > 0)
Console.Write("i{0} ", _i);
if (_j > 0)
Console.Write("j{0} ", _j);
Console.ReadKey();
}
private static void DoWork()
{
for (int x = 0; x < N; x++)
{
lock (_l)
{
// i-thread has run?
if (_i > 0)
{
// print and reset i
Console.Write("i{0} ", _i);
_i = 0;
}
_j++;
}
}
}
}

Why am I getting unexpected output when spawning threads?

I was trying to spawn certain number of threads. But when I pass arguments to the function the output is random. It chooses some values of variable 'i' for multiple times and ignores some. I am a newbie in C#. Please explain if I am doing anything wrong.
using System;
using System.Threading;
public class first
{
public static void tone(int i)
{
Console.WriteLine("Hi ! this is thread : {0} ",i);
Thread.Sleep(10);
}
public static void Main(String[] args)
{
int i;
for (i = 0; i < 10; i++)
{
Thread th1 = new Thread(()=>tone(i) );
th1.Start();
// Console.WriteLine(i);
}
Console.WriteLine("hey there!");
Console.ReadLine();
}
}
Because of closure:
Change your code to:
int i;
for (i = 0; i < 10; i++)
{
int j = i;
Thread th1 = new Thread(()=>tone(j) );
th1.Start();
// Console.WriteLine(i);
}

Wait for threads to complete

private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 15; i++)
{
Thread nova = new Thread(Method);
nova.Start();
}
listBox1.Items.Add("Some text");
}
private void Method()
{
for (int i = 0; i < 15; i++)
{
Console.WriteLine(i);
}
}
This code does write: Some text and then numbers 111222333.....
I would like that it writes 111122223333.... and then on the end Some text.
is it possible to do that with threads (parent thread wait for child threads)? or do i have to use something else?
You need to keep track of all the threads, and use Thread.Join on each one. This waits until the specified thread terminates, and then continues executing. Like this:
var threads = new List<Thread>();
for (int i = 0; i < 15; i++)
{
Thread nova = new Thread(Method);
nova.Start();
threads.Add(nova);
}
foreach (var thread in threads)
thread.Join();
listBox1.Items.Add("Some text");
I suggest to use TPL to get this done. You won't need to spawn so many threads. By default TPL will use thread pool for that:
using System;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
private const int TaskCount = 15;
static void Main(string[] args)
{
var tasks = new Task[TaskCount];
for (var index = 0; index < TaskCount; index++)
{
tasks[index] = Task.Factory.StartNew(Method);
}
Task.WaitAll(tasks);
Console.WriteLine("Some text");
}
private static void Method()
{
for (int i = 0; i < 15; i++)
{
Console.WriteLine(i);
}
}
}
}
You could have two threads, the 2nd one waiting on a signal to fire from the first.
private void Foo()
{
var signals = new List<ManualResetEvent>();
for (int i = 0; i < 15; i++)
{
var signal = new ManualResetEvent(false);
signals.Add(signal);
var thread = new Thread(() => { Method(); signal.Set(); });
thread.Start();
}
var completionTask = new Thread(() =>
{
WaitHandle.WaitAll(signals.ToArray());
CompletionWork();
});
completionTask.Start();
}
private void Method()
{
}
private void CompletionWork()
{
}
The better solution now with .Net 4.0 (and later) is to use Tasks, and invoke a method using ContinueWith
private void Foo()
{
var childThreads = new List<Task>();
for (int i = 0; i < 15; i++)
{
var task = new Task(Method);
task.Start();
childThreads.Add(task);
}
var completionTask = new Task(() =>
{
Task.WaitAll(childThreads.ToArray());
}).ContinueWith(t => CompletionWork());
}
private void Method()
{
}
private void CompletionWork()
{
}
The join answers also work, but require the containing thread to block. If you don't want the GUI to block, Spawn an additional thread around the 1st.
You can use thread.join to wait for threads to end. See http://www.dotnetperls.com/thread-join for an page on how to use it.

C# Maintain 3 threads and close one if it takes to long

This is the code I am using to call 3 threads.
for (int i = 0; i < 3; i++)
{
new Thread(() => { processEventLogTesting(); }) {IsBackground = true }.Start();
}
I was thinking about adjusting it to this
public static int ThreadCounter = 0;
if (ThreadCounter < 3)
{
ThreadCounter ++;
for (int i = 0; i < 3; i++)
{
new Thread(() =>
{
processEventLogTesting(/*somewhere in here code says */ThreadCounter--;);}) {IsBackground = true }.Start();
}
}
}
However, I think this is probably not the best way to do this. Also, I want to put in a new timer that says if thread x goes over 20 minutes, kill thread x. Any help is appreciated.
Since I don't know what thread does, I would try something like this
private Object lockObject = new Object();
private int threadCounter = 0;
public int ThreadCounter
{
get
{
lock(lockObject)
{
return threadCounter;
}
}
set
{
lock(lockObject)
{
threadCounter = value;
}
}
}
//this should be a method
if (ThreadCounter < 3)
{
ThreadCounter ++;
new Thread(() =>
{
Timer t = new Timer(() => EndThread(), null, 0, 20 * 60 * 1000);
while(threadIsRunning)
{
processEventLogTesting(/*somewhere in here code says ThreadCounter--*/;);
}
}) {IsBackground = true }.Start();
}
}
}
private void EndThread()
{
threadIsRunning = false;
}

Wait until all threads finished their work in ThreadPool

i have this code:
var list = new List<int>();
for(int i=0;i<10;i++) list.Add(i);
for(int i=0;i<10;i++)
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(x => {
Console.WriteLine(x);
}), list[i]);
}
And i want to know when all threadpools threads finished their work. How i can to do that?
You'll need to track this yourself.
One option for this is to use a counter and a reset event:
int toProcess = 10;
using(ManualResetEvent resetEvent = new ManualResetEvent(false))
{
var list = new List<int>();
for(int i=0;i<10;i++) list.Add(i);
for(int i=0;i<10;i++)
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(x => {
Console.WriteLine(x);
// Safely decrement the counter
if (Interlocked.Decrement(ref toProcess)==0)
resetEvent.Set();
}),list[i]);
}
resetEvent.WaitOne();
}
// When the code reaches here, the 10 threads will be done
Console.WriteLine("Done");
In .NET Framework 4+ use the handy System.Threading.CountdownEvent class:
const int threadCount = 10;
var list = new List<int>(threadCount);
for (var i = 0; i < threadCount; i++) list.Add(i);
using (var countdownEvent = new CountdownEvent(threadCount))
{
for (var i = 0; i < threadCount; i++)
ThreadPool.QueueUserWorkItem(
x =>
{
Console.WriteLine(x);
countdownEvent.Signal();
}, list[i]);
countdownEvent.Wait();
}
Console.WriteLine("done");
I am not sure if ThreadPool exposes such functionality but you can use wait handles and by the way iterating twice seems unnecessary:
var events = new ManualResetEvent[10];
var list = new List<int>();
for (int i = 0; i < 10; i++)
{
list.Add(i);
events[i] = new ManualResetEvent(false);
int j = i;
ThreadPool.QueueUserWorkItem(x => {
Console.WriteLine(x);
events[j].Set();
}, list[i]);
}
WaitHandle.WaitAll(events);
This is how I would do it.
class Program
{
static void Main(string[] args)
{
var items = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
using (var countdown = new Countdown(items.Length))
{
foreach (var item in items)
{
ThreadPool.QueueUserWorkItem(o =>
{
Thread.SpinWait(100000000);
Console.WriteLine("Thread Done!");
countdown.Signal();
});
}
countdown.Wait();
}
Console.WriteLine("Job Done!");
Console.ReadKey();
}
public class Countdown : IDisposable
{
private readonly ManualResetEvent done;
private readonly int total;
private volatile int current;
public Countdown(int total)
{
this.total = total;
current = total;
done = new ManualResetEvent(false);
}
public void Signal()
{
lock (done)
{
if (current > 0 && --current == 0)
done.Set();
}
}
public void Wait()
{
done.WaitOne();
}
public void Dispose()
{
done.Dispose();
}
}
}
The thread pool does not tell you when the thread has finished executing, so the work item must do it itself. I changed the code like this:
var list = new List<int>();
ManualResetEvent[] handles = new ManualResetEvent[10];
for (int i = 0; i < 10; i++) {
list.Add(i);
handles[i] = new ManualResetEvent(false);
}
for (int i = 0; i < 10; i++) {
ThreadPool.QueueUserWorkItem(
new WaitCallback(x =>
{
Console.WriteLine(x);
handles[(int) x].Set();
}), list[i]);
}
WaitHandle.WaitAll(handles);
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(xyz));
}
bool working = true;
ThreadPool.GetMaxThreads(out int maxWorkerThreads, out int maxCompletionPortThreads);
while (working)
{
ThreadPool.GetAvailableThreads(out int workerThreads, out int completionPortThreads);
//Console.WriteLine($"{workerThreads} , {maxWorkerThreads}");
if (workerThreads == maxWorkerThreads)
{ working = false; }
}
//when all threads are completed then 'working' will be false
}
void xyz(object o)
{
console.writeline("");
}

Categories