C# Joining Threads
In C#, multiple threads can be created and run concurrently to perform parallel tasks. Sometimes it is necessary to wait for one thread to finish its execution before proceeding or for all threads to complete before continuing further. The Thread.Join() method allows one thread to wait for another thread's completion, ensuring proper synchronization. This article explains how to join threads using Thread.Join() and Task.WaitAll() with examples.
1. Thread.Join() Method
The Join method of the Thread class waits for the thread to complete its execution before continuing with the execution of the calling thread. This method blocks the calling thread until the target thread has completed its execution.
Syntax:
public void Join();
public bool Join(int millisecondsTimeout);
public bool Join(TimeSpan timeout);
- Join(): It blocks the calling thread until the target thread terminates.
- Join(int millisecondsTimeout): It waits for the specified duration (in milliseconds) or until the thread terminates, whichever occurs first.
- Join(TimeSpan timeout): It is similar to the above but uses TimeSpan.
Example:
// Using Thread.Join() to synchronize threads
using System;
using System.Threading;
class Geeks
{
static void Main(string[] args)
{
// Create two threads to perform tasks
Thread t1 = new Thread(()
=> Console.WriteLine("Thread 1 started."));
Thread t2 = new Thread(()
=> Console.WriteLine("Thread 2 started."));
// Start the threads
t1.Start();
t2.Start();
// Wait for both threads to
// complete before proceeding
t1.Join();
t2.Join();
Console.WriteLine("Main Thread execution completed.");
}
}
Output
Thread 2 started. Thread 1 started. Main Thread execution completed.
Overloaded Methods in Thread.join()
Thread class provides the Join() method, which allows one thread to wait until another thread completes its execution. If "t" is a Thread object, "t.Join()" causes the current thread to pause its execution until the thread represented by "t" terminates. There are some versions of in Join() method which provide more control on Threads. The Join() method has the following overloads:
- Join() Method
- Join(Int32) Method
- Join(TimeSpan) Method
1. Join() Method
This method blocks the calling thread until the thread represented by this instance terminates while continuing to perform standard COM (Component Object Model) and SendMessage pumping.
Syntax:
public void Join ();
2. Join(Int32) Method
This method blocks the calling thread for the specified number of milliseconds or until the target thread terminates, whichever occurs first. Returns true if the target thread terminates before the timeout expires, false otherwise.
Syntax:
public bool Join (int millisecondsTimeout);
3. Join(TimeSpan) Method
This method blocks the calling thread for the specified duration or until the target thread terminates, whichever occurs first. Returns true if the target thread terminates before the timeout expires, false otherwise.
Syntax:
public bool Join (TimeSpan timeout);
Example 1:
// C# program to illustrate the
// concept of Join() method
using System;
using System.Threading;
public class ExThread
{
public void mythread()
{
for (int x = 0; x < 4; x++)
{
Console.WriteLine(x);
Thread.Sleep(100);
}
}
public void mythread1()
{
Console.WriteLine("2nd thread is Working..");
}
}
public class Geeks
{
public static void Main()
{
// Creating instance for
// mythread() method
ExThread o = new ExThread();
// Creating and initializing threads
Thread t1 = new Thread(new ThreadStart(o.mythread));
Thread t2 = new Thread(new ThreadStart(o.mythread1));
t1.Start();
// Join thread
t1.Join();
t2.Start();
}
}
Output
0 1 2 3 2nd thread is Working..
Explanation: In the above example,
- We have a non-static method, i.e. mythread() and mythread1(). So we create an instance, i.e. "o" of ExThread class and refer it in the constructor of ThreadStart class.
- Using Thread t1 = new Thread(new ThreadStart(o.mythread)); statement we create a thread named as t1 and initialize the work of this thread, similarly for thread t2.
- By using t1.Join(); statement, we will send the calling of t2 into waiting until the work of t1 thread is completed.
- After that t2 thread executes.
Example 2:
// C# program to illustrate the
// concept of Join() method
using System;
using System.Threading;
class Geeks
{
// Creating TimeSpan for thread
static TimeSpan ts = new TimeSpan(0, 0, 0, 0, 500);
public static void Main()
{
// Creating and initializing new thread
Thread t = new Thread(mywork);
t.Start();
if (t.Join(ts + ts))
{
Console.WriteLine("New thread is terminated");
}
else
{
Console.WriteLine("Join timed out");
}
}
static void mywork()
{
Thread.Sleep(ts);
}
}
Output
New thread is terminated
2. Task.WaitAll()
The WaitAll method of the Task class waits for all the specified tasks to complete before continuing with the execution of the calling thread. This method blocks the calling thread until all the specified tasks have completed their execution.
Example:
// Example: Using Task.WaitAll() to
// wait for tasks to complete
using System;
using System.Threading.Tasks;
class Geeks
{
static void Main(string[] args)
{
// Create and run tasks
Task t1 = Task.Run(()
=> Console.WriteLine("Task 1 is running."));
Task t2 = Task.Run(()
=> Console.WriteLine("Task 2 is running."));
// Wait for all tasks to complete
Task.WaitAll(t1, t2);
Console.WriteLine("Main Thread execution completed.");
}
}
Output
Task 1 is running. Task 2 is running. Main Thread execution completed.