Wait for threads to complete - c#

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.

Related

I can not recreate thread competing effect

I read, in many many articles, that multiple threads will "compete" for the same resource and try to recreate it with the following code:
static void Main(string[] args)
{
List<int> list = new List<int>();
Thread t1 = new Thread(thread1);
t1.IsBackground = true;
t1.Start();
Thread t2 = new Thread(thread2);
t2.IsBackground = true;
t2.Start();
Thread.Sleep(3000);
foreach(int i in list)
{
Console.WriteLine(i);
}
Console.ReadLine();
void thread1()
{
for (int i = 0; i < 10000; i++)
{
list.Add(i);
}
}
void thread2()
{
for (int i = 10000; i < 20000; i++)
{
list.Add(i);
}
}
}
But the result is still very "nice and neat" in order (from 0 to 19999), what did I do wrong?

HelloWorld Multithreaded C# app with double input and output

Consider the following example taken from HelloWorld Multithreaded C# app
using System;
using System.Threading;
class ThreadTest
{
static void Main()
{
Thread t = new Thread (WriteY); // Kick off a new thread
t.Start(); // running WriteY()
// Simultaneously, do something on the main thread.
for (int i = 0; i < 1000; i++) Console.Write ("x");
}
static void WriteY()
{
for (int i = 0; i < 1000; i++) Console.Write ("y");
}
}
is there a way to have a function like "static double WriteY (double a)" instead of "static void WriteY()" ?
I am not sure what you want to do with return value of Write method, but I think i get your intention and modified your code snippet to address what you looking for :
class ThreadTest
{
static void Main()
{
Task t = Task.Run(() => Write(5));
// Simultaneously, do something on the main thread.
for (int i = 0; i < 1000; i++) Console.Write ("x");
t.wait();
}
static double Write(double a)
{
for (int i = 0; i < 1000; i++) Console.Write("y");
return a;
}
}

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++;
}
}
}
}

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

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