C#Multithreading - Thread sleep, interrupt, merge, pause and resume, terminate

Posted by dhiren22 on Mon, 31 Jan 2022 18:49:22 +0100

1. Sleep

Sleep(int millisecondsTimeout)

Thread. Sleep (int milliseconds Timeout) also has an overloaded Thread.Sleep(TimeSpan timeout) is used to suspend the current thread for a certain amount of time, during which time CPU usage is discarded, and it is time to automatically restore the thread and other threads to participate in CPU competition.

 //Call - Static method of Thread class
 Thread.Sleep(1000);//Suspend the current process for 1000ms
 
 Timespan ts=new Timespan(1,20,33);//Create an interval object of 1 hour, 22min33s
 Thread.Sleep(ts);//Suspend the current thread for 1h22min33s
 

SpinWait(int iterations)

Thread.SpinWait(int iterations) is also a static method of the Thread class that allows the current thread to wait a certain amount of time (ms units) for a period of time without giving up CPU usage, similar to having the CPU execute an invalid piece of code.

//call
Thread.SpinWait(1000);//Wait the current thread for 1000ms and execute immediately after the wait does not require re-participating in CPU competition

Interrupt

The Interrupt method can only interrupt a thread in the WaitSleepJoin state, throw an exception and change the state of the thread, and the thread will resume execution.
If a thread is blocked (such as when blocking methods such as Sleep(), Join(), and I/O operations on interrupt channels are called), when the thread state is WaitSleepJoin, a ThreadInterruptException exception is thrown at the blocked method call and the thread state is set to another state after the exception is thrown so that the thread wakes up from the blocked state. And give the programmer enough time to process the interrupt request before ending the thread.

//call
thread.Interupt();

3. Merge Join

thread.Join() indicates that a threaded thread prevents calling other threads before termination, and automatically restores the original thread after termination. This method is often used in other threads or in the main thread to temporarily force priority execution on on a particular thread.

//call
thread.Join();//Can have parameters indicating the length of merge

4. Suspension and Recovery

C# has discarded unsafe Supend () and Resume(), and now suspension and grayscale of threads can be achieved through two blocking event classes, AutoResetEvent and ManualResetEvent.

The difference between the two events

  • AutoResetEvent is automatically blocked, allowing only one thread to pass through once and then continue blocking, similar to a temperature measurement at a community gate
  • ManualResetEvent is manually blocked and needs to be blocked manually after opening, otherwise it will always open; Blocked need to be opened manually, otherwise it will be blocked all the time, like a tap

Set(), Reset(), and WaitOne()

  • WaitOne() blocks the thread and waits for a signal; Overloads with parameters, set wait times, and wait timeouts
  • The Set() method can emit a passable signal
  • The Reset() method can emit an inaccessible signal

Use

  • AutoResetEvent
public class
{
    //Instantiates an AutoResetEvent object, with the bool parameter representing the initial state of are and the true parameter representing the
    private static AutoResetEvent are = new AutoResetEvent(true);
    Thread th=new Thread(new ThreadStart(ThTest));
    private static ThTest()
    {
        are.WaitOne();
        Console.WriteLine(1);
        are.WaitOne();
        Console.WriteLine(2);
        are.WaitOne();
        Console.WriteLine(3);
    }
    
    Principal function()
    {
        th.Start();
        Console.ReadLine();
        are.Set();
    }
    
    //output
    1
    2
    
    //analysis
    //Encountered the first are. When WaitOne (), because the initial state of the blocked event object is passable (true), th passes directly, and the state of the are changes to not passable, then output 1
    //Encountered the second are. When WaitOne (), th are is blocked because the are state is not passable, waiting for other threads to signal.
    //Are on the main thread. Set () sends a signal that passes through are, and th passes through the second are.WaitOne(), while Are's status changes to not passable, output 2
    //Encountered the third are.WaitOne(), th is blocked again, it can only wait until the main thread ends and fails, th is forcibly terminated
    //Reset() in AutoResetResult is commonly used for internal thread self-blocking
}
  • ManualResetEvent
public class
{
    //Instantiates a ManualResetEvent object, with the bool parameter indicating the initial state of the mre and the false parameter indicating no passing
    private static ManualResetEvent mre = new ManualResetEvent(false);
    Thread th=new Thread(new ThreadStart(ThTest));
    private static ThTest()
    {
        mre.WaitOne();
        Console.WriteLine(1);
        mre.WaitOne();
        Console.WriteLine(2);
        mre.Reset();
        mre.WaitOne();
        Console.WriteLine(3);
        mre.WaitOne();
        Console.WriteLine(4);
    }
    
    Principal function()
    {
        th.Start();
        Console.ReadLine();
        mre.Set();
    }
    
    //output
    1
    2
    
    //analysis
    //Encountered the first mre. When WaitOne(), th is blocked because the initial state of the blocking event object MRE is not passable (false)
    //The main thread sends the mre.Set() makes the MRE pass through, and th passes through the first mre.WaitOne(), output 1
    //Next came a second mre.WaitOne(), the MRE status passes, and th passes through the second mre.WaitOne(), output 2
    //At this point the mre state is set to be inaccessible within the thread
    //Encountered a third mre. When WaitOne (), th is blocked, MRE status is not passable, th is waiting
    //th was forcibly terminated until the main thread ended and failed
}

Thread Abort

Threads cannot be restarted once aborted.

  • Cooperative Cancellation
  • Abort()
  • return

Cooperative Cancellation - Stop the thread correctly

  • Similar to AutoResetEvent and ManualResetEvent, it responds to the caller's request by opening the caller interface (passing semaphores) within the thread itself and detecting the corresponding identity while working: ++ Cancled++.
  • Unlike Abort(), it does not depend on what the user does, but on whether the thread can actively respond to the stop request.
  • Mechanisms: The thread detects the Cancled identity at some frequency while it is working. If Cancled is detected, the thread is responsible for exiting itself.
static void Main(string[] args)
		{
			CancellationTokenSource cts = new CancellationTokenSource();
			Thread t = new Thread(() =>
			{
				while(true)
				{
					if(cts.Token.IsCancellationRequested)
					{
						Console.WriteLine("Cancled Signal trigger!");
						Console.WriteLine(Thread.CurrentThread.ThreadState.ToString());
						break;
					}
					Console.WriteLine(DateTime.Now.ToString());
					Thread.Sleep(1000);
				}
				Console.WriteLine("Thread termination!");
			});
			t.Start();
			Console.ReadLine();
			cts.Cancel();
			Console.WriteLine("main:Thread stopped!");
			Console.WriteLine(t.ThreadState.ToString());
			Console.ReadKey();
			Thread.Sleep(2000);
			Console.WriteLine(t.ThreadState.ToString());
			Console.ReadKey();
		}
		
//output
2021/6/2 11:38:47
2021/6/2 11:38:48
2021/6/2 11:38:49
2021/6/2 11:38:50
2021/6/2 11:38:51

main:Thread stopped!
WaitSleepJoin
Cancled Signal trigger!
Running
 Thread termination!
Stopped

Abort() terminates a thread immediately

ThreadAbortException exception is thrown on the current thread when Abort() terminates the current thread and is only useful for managed code. ThreadAbortException is a special exception that can be caught by the application and is automatically re-thrown in the catch block unless the ResetAbort method is called in the catch block. Thread.ResetAbort() cancels the termination request and prevents ThreadAbortException thrown again in the catch from terminating the current thread. Finally blocks that are not executed are executed before the thread terminates.

tips:1·Managed code refers to CLR Code responsible for managing execution (hosting), often with IL(Intermediate Language) CLR Execution; 2·Unmanaged code refers to code that is executed directly on the machine by the operating system and is not enjoyable CLR Services such as memory management, typically MFC,WIN32,ALT And so on.

Detailed

public class ThreadWork
{
    public static void DoWork()
    {
        try
        {
            ... //Content of try
        }
        catch (ThreadAbortException e)
        {
            ... //Contents of catch
            
            //Thread.ResetAbort();
            
            ... //Contents of catch
        }
        finally
        {
            ... //finally content
        }
        
        ... //Thread Remaining
    }
}
  • If Thread is called in catch. ResetAbort()
  1. Cancel the request to terminate the thread, restore the thread, continue executing the statement after ResetAbort, and execute the statement after the catch block
  2. If there is a Finally block after the Catch block, execute the Finally block, and then execute the statement after the Finally block.
  • If Thread is not called. ResetAbort()
  1. A finally block executes before the thread terminates, statements following the finally block are not executed, and the thread terminates.
  • Code in catch and finally must be executed

usage

// Thread Internal Writing Reference

// Parts in other threads: Since Abort() executes part of the code after it, the thread does not stop immediately. To prevent code in catch and finally from taking too long to affect other threads, we need to do something to wait for the thread to complete or terminate.
//1. Loop wait
th.Abort();
while(th.ThreadState!=ThreadState.Aborted)
{
    //When the Abort method is called, if the thread thread's state is not Aborted, the main thread loops here until the thread thread's state becomes Aborted
    Thread.Sleep(100);
}
//When we jump out of the loop above, the thread s we started have completely terminated
···


//2. Join Waits
th.Abort();
th.Join();
···

Time of Abort Call

  1. Call Abort before thread Start
    Threads terminate when Start is called.

  2. Call Abort when thread Sleeping
    Thread is interrupted and terminated

  3. Call Abort when thread Blocked
    Thread is interrupted and terminated

  4. Call Abort when a thread is suspended
    Throw ThreadStartException raises a call to Abort, and AbortRequested is added to the ThreadState property of the thread being terminated

  5. Call Abort while a managed thread is executing unmanaged code
    ThreadAbortException will not be thrown until the thread returns managed code.

  6. If you have two Abort threads at the same time, it is possible that one thread will set state information and the other thread will execute Abort's method. However, the application will not detect this.

Note that the Abort method forces the end of the thread by throwing a ThreadAbortException exception, using as little as possible.

Universal return

Multithreading actually calls a stack of methods, return s can end methods, and the bad news is
return contamination may occur, affecting other methods.

Collaborative stop threads are officially recommended writings, and the principle of personal understanding is to pass a global variable to notify the thread that it is unnecessary to use the class it is given and may have other uses. Individuals prefer Abort() and return, and Abort() is used when an action is required to stop the request because exceptions can be caught; Just stop and return immediately.

Attachment: ThreadState status table

public enum ThreadState
	{
		Running = 0x0,
		StopRequested = 0x1,
		SuspendRequested = 0x2,
		Background = 0x4,//Background threads end (force) as the main thread ends, and only when the foreground thread has executed all the main thread can it end
		Unstarted = 0x8,
		Stopped = 0x10,
		WaitSleepJoin = 0x20,
		Suspended = 0x40,
		AbortRequested = 0x80,
		Aborted = 0x100
	}

Topics: C#