A thread is defined as the execution path of a program. Each thread defines a unique flow control. If your application involves complex and time-consuming operations, such as database access or some intense I/O operations, then it is often very beneficial to set up different execution paths or threads, each thread performing a specific job.
Threads are lightweight processes. A common example of the use of threads is the implementation of parallel programming in modern operating systems. Using threads saves the loss of CPU cycles and improves application efficiency.
The program we have compiled so far runs as a single process on a thread, which is the running instance of the application. However, such an application can only perform one job at a time. To have it perform multiple tasks at the same time, you can divide it into smaller threads.
In .Net, threads are handled through the 'System.Threading' namespace. Creating variables of type system.threading.thread allows you to create a new thread to start working on. It allows you to create and access independent threads in a separate thread.
A thread is created from a thread object, and its constructor is given a reference to starting the thread.
ThreadStart childthreat = new ThreadStart(childthreadcall);
The life cycle of a thread begins when an object of the system.threading.thread class is created and ends when the thread is terminated or execution is completed.
The following are the various states in the life cycle of a thread:
Pending start state: The instance of the thread has been created but the startup method has not been called.
Ready state: A situation when a thread is ready to execute and waiting for a CPU cycle.
Unrunnable state: When a thread cannot be run, there are several possibilities:
The current sleep method is called
Waiting method is called
Blocked by I/O operation
Death state: The thread has completed execution or has been terminated.
The priority attribute in the Thread class mainly specifies the priority of a thread relative to other threads. The .NET runtime selects the ready thread with the highest priority. Priority can be divided into:
higher than normal
lower than normal
Highest
lowest
normal
Once a thread is created, the system sets its priority using the Thread class's priority setting system.
NewThread.Priority = ThreadPriority.Highest;
The thread class has the following important features:
property | describe |
---|---|
CurrentContext | Get the contents of the currently executing thread. |
CurrentCulture | Gets or sets the environment of the current thread. |
CurrentPrinciple | Gets or sets the role-based security policy of the current process. |
CurrentThread | Get the currently running thread. |
CurrentUICulture | Gets or sets the current environment used by the currently running process's resource manager to find specific resources. |
ExecutionContext | Gets an ExecutionContext object that contains contextual information about the current thread. |
IsAlive | Gets a value indicating the execution status of the current thread. |
IsBackground | Background Gets or sets a value indicating whether the thread is a background thread. |
IsThreadPoolThread | Gets a value indicating whether the thread belongs to the managed thread pool. |
ManagedThreadId | Gets the current unique identifier of the managed thread. |
Name | Gets or sets the name of the thread. |
Priority | Gets or sets a value indicating the scheduling priority of a thread. |
ThreadState | Gets a value containing the status of the current thread. |
The thread class has the following important methods:
method | describe |
---|---|
Abort | Calling a ThreadAbortException begins the process of terminating the thread. Calling this method usually terminates the thread. |
AllocateDataSlot | All threads are assigned an unnamed data slot. For better performance, use fields marked with the ThreadStaticAttribute attribute. |
AllocateNamedDataSlot | Allocate named data slots to all threads. For better performance, use fields marked with the ThreadStaticAttribute attribute. |
BeginCriticalRegion | Notifies the host that execution is about to enter a code region where the effects of a thread abort or an unhandled exception could compromise other tasks. |
BeginThreadAffinity | Notifies the host that managed code is about to execute, depending on the identity of the current physical operating system thread. |
EndCriticalRegion | Notifies the host that execution is about to enter a region of code where a thread abort or an unhandled exception affects only the current task. |
EndThreadAffinity | Notifies the host that managed code execution is complete, depending on the identity of the current physical operating system thread. |
FreeNamedDataSlot | Eliminates the association between names and slots for all threads in the process. For better performance, use fields marked with the ThreadStaticAttribute attribute. |
GetData | Retrieves a value from the slot specified by the current thread in the current domain of the current thread. For better performance, use fields marked with the ThreadStaticAttribute attribute. |
GetDomain | Returns the currently executing thread in the current domain. |
GetDomainID | Returns the unique application domain identifier. |
GetNamedDataSlot | Find a named data slot. For better performance, use fields marked with the ThreadStaticAttribute attribute. |
Interrupt | Interrupt a thread in WaitSleepJoin thread state. |
Join | Blocks the calling thread until one of the threads terminates, while continuing standard COM and SendMessage execution. This method has different overloaded forms. |
MemoryBarrier | Synchronous memory accesses are as follows: the accelerator processing the current thread cannot reorder instructions in such a way that the memory access calls MemoryBarrier followed by the memory access execution. |
ResetAbort | Cancels the current thread's abort request. |
SetData | Sets the data for the current running thread on the specified time slot, and the current domain of that thread. For better performance, the application domain has the ThreadStaticAttribute attribute of the domain. |
Start | Start a thread. |
Sleep | Causes the thread to pause for a period of time. |
SpinWait | Makes the thread wait for the number of iterations defined by the parameter. |
VolatileRead() | Read the value of the field. The latest value is written by any processor of the computer, regardless of the processor or processor cache state number. This method has different overloaded forms. |
VolatileWrite() | Immediately writes a value to a field that is visible to all processors in the computer. This method has different overloaded forms. |
Yield | Causes the calling thread to execute another thread that can run on the current processor, and the operating system chooses to redirect the thread |
The following example illustrates the use of thread classes. The page has a control label that displays messages from child threads. Messages from the main program are displayed directly using the response.write(50) method, so they appear at the top of the page.
The source files are as follows:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="threaddemo._Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional// EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title> Untitled Page </title> </head> <body> <form id="form1 " runat="server"> <div> <h3>Thread Example</h3> </div> <asp:Label ID="lblmessage" runat="server" Text="Label"> </asp:Label> < /form> </body> </html>
The background code is as follows:
using System; using System.Collections; using System.Configuration; using System.Data; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls ; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; using System.Threading; namespace threaddemo { public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { ThreadStart childthreat = new ThreadStart(childthreadcall); Response.Write("Child Thread Started <br/>"); Thread child = new Thread(childthreat); child.Start(); Response.Write("Main sleeping for 2 seconds....<br/>"); Thread.Sleep(2000); Response.Write("<br/>Main aborting child thread<br/>"); child.Abort(); } public void childthreadcall() { try{ lblmessage.Text = "<br/ >Child thread started <br/>"; lblmessage.Text += "Child Thread: Coiunting to 10"; for( int i =0; i<10; i++) { Thread.Sleep(500); lblmessage.Text += "<br/> in Child thread </br>"; } lblmessage.Text += "<br/> child thread finished"; } catch(ThreadAbortException e){ lblmessage.Text += "<br /> child thread - exception"; }finally{ lblmessage.Text += "<br /> child thread - unable to catch the exception"; } } } }
When the page is loaded, a new thread is started with childthreadcall() as a reference. The activities of the main thread will be displayed directly on the web page.
A second thread runs and sends the message to the control tag.
The main thread sleeps for 2000 milliseconds while the child thread is executing.
The child thread continues to run until it is terminated by the main thread, then it throws a ThreadAbortException and is terminated.
Control returns to the main thread.
When executed the program will send the following information: