Reader Level:
ARTICLE

Naming, passing data and capturing variables in Thread

Posted by Akshay Teotia Articles | Multithreading in C# November 26, 2011
We know that every thread has a name property that you can set for the benefit of debugging. Thread’s name is displayed in the threads window and debug location toolbar.
  • 0
  • 0
  • 5385

Naming Thread

We know that every thread has a Name property that you can set for the benefit of debugging. Thread's name is displayed in the Threads Window and Debug Location toolbar. The static Thread.CurrentThread property gives you the name of current thread. You can set the Name property once in visual studio if we try to change it again this will throw a exception.

In the following example, we implement the Thread.CurrentThread property for naming the thread.

using
System;
using System.Diagnostics;
using System.Threading;
namespace Threadnaming
{
    class Program
    {
        static void Run()
        {
            Console.WriteLine("welcome to the " + Thread.CurrentThread.Name +" world");
        }
       
        static void Main(string[] args)
        {
            Thread.CurrentThread.Name = "MCN";
            Thread website = new Thread(Run);
            website.Name = "C#Corner";
            website.Start();
            Run();
            Console.Read();
        }
    }
}

Output

thnaming.gif

Passing Data to a Thread

We can pass arguments to a thread's target method is to execute a lambda expression that calls the method with the desired arguments. With this approach, you can supply in any number of arguments to the method.

using System;
using System.Threading;
using System.Diagnostics;
namespace passingdatatoathread
{
    class Akshay
    {
        static void display(string message)
        {  

          Console.WriteLine(message);
        }
        static void Main(string[] args)
        {
            Thread th = new Thread(() => Console.WriteLine("Hello from th!"));
            th.Start();
            Console.Read();
        }
    }
}

Output

passdata.gif

You can even wrap the entire implementation in a multi-statement lambda:

new Thread(() =>
{
      Console.WriteLine("I'm processing on another thread!");
      Console.WriteLine("This is so easy!");
}).Start();

Lambda expressions and captured variables

As we saw, a lambda expression is the esay way to pass data to a thread. However, You need to keep care when  abnormally modifying captured variables after thread is start, because these variables are shared. For instance, consider the following:

for (int i = 0; i < 10; i++)
      new Thread(() => Console.Write(i)).Start();

The output of above program is unaccepted

0223557799

The problem is that the 'i' variable refers throughout the loop's lifetime same memory location. Therefore, each thread calls Console.Write on a variable whose value may change as it is running! The solution is to use a temporary variable as follows:

for (int i = 0; i < 10; i++)
{
      int temp = i;
      new Thread(() => Console.Write(temp)).Start();
}

Now temp variable work like a local variable for each iteration of loop. therefore the problem is solve because each thread captures a different memory location.

you can simplified the above code as:

    string text = "t1";
    Thread t1 = new Thread(() => Console.WriteLine(text));
   
text = "t2";
    Thread t2 = new Thread(() => Console.WriteLine(text));
    t1.Start();
    t2.Start();

Because both lambda expressions capture the same text variable, t2 is printed twice as.

t2
t2

Foreground and Background Threads

Foreground thread are used to alive are application as long as any of the thread is running .By default, threads you create explicitly are foreground threads. whereas background threads do not. Once all foreground threads finish, the application ends, and any background threads still running suddenly terminate.

You can query or change a thread's background status using its IsBackground property. Here's an example:

class PriorityTest
{
      static void Main (string[] args)
      {
            Thread emp = new Thread ( () => Console.ReadLine() );
            if (args.Length > 0) emp.IsBackground = true;
                emp.Start();
      }
}

When we call this program with no argument the emp thread assumes foreground status and it will wait on the ReadLine statement for the user to press Enter. Meanwhile, the main thread exits, but the application is in the running mode because a foreground thread is still alive.

In another way , if you supply an argument to the Main(), the emp is assigned background status, and the program exits almost immediately as the main thread ends (terminating the ReadLine).

If a process terminate like as. this is happen because of your program employs finally (or using) blocks to perform cleanup work such as releasing resources or deleting temporary files. To overcome this problem you need to wait until explicitly background threads upon exiting an application. you can achieve this by to ways.

  • If you've created the thread yourself, call Join on the thread.

  • If you're on a pooled thread, use an event wait handle.

Sometime u can give a timeout to abandon a renegade thread which is refuse to finish for some reason. This is your backup exit strategy: in the end, when you want to close your application without taking the help of Task Manger.

This process is not require for foreground thread. But you need to take care to avoid bugs that could cause the thread not to end. Some time the presence of active foreground thread create hurdle for termination or exit of any application.

When a user use the task manager forcefully terminate the .Net process then the all thread are dead as though they were background threads. This is observe fact rather than a documented data. and it could be differ depending on the version of CLR and operating system.

COMMENT USING