How to cancel the execution of. NET background Threads _ Practical Tips

Source: Internet
Author: User
Tags readline thread class
Introduced
One of the common problems in programming with multithreaded models is that when we close the UI thread in the foreground, the worker thread in the background is still active, causing the entire application to fail gracefully. At this point we need a more secure way to end the running of the background thread so that we can end the running of the background thread at any time, and do the appropriate resource cleanup at the end of the thread (such as writing the memory data to the hard disk). The. NET Framework provides tools to implement this functionality.

Directory
IsBackground Property
Abort method
Round-robin Mode
Unblock a blocked thread
Isbackgound Property
The thread class provides the IsBackground property, which indicates that this thread is a background worker when the thread's IsBackground property is set to true. When an application ends, all of its background threads are automatically terminated. If you have a background thread that listens for the socket connection and is blocking, then it is appropriate to automatically end the application by setting the thread's IsBackground property to True. But in this case, the thread will end silently, it will not throw any exceptions, and your thread has no chance to perform some of the required cleanup code. For example, data in memory may be too late to write to disk, causing data loss.

Abort Method
You can call the Abort method of the thread class to force the end thread. When this method is invoked, a ThreadAbortException is raised on the thread and is directed to the end of the thread, and some resource cleanup code can be performed by capturing the exception. However, there are also some problems with this pattern, mainly because it is difficult to know where the code execution on the thread is, and all the corresponding resource cleanup code is difficult to write. In general, this is a relatively crude way to terminate thread execution, which is generally not recommended.

round-robin mode
If the background thread performs a long calculation, you can separate the calculations into small segments and often check to see if the thread needs to be canceled. NET Framework provides a unified pattern of CancellationTokenSource classes to be canceled as threads. For example:
Copy Code code as follows:

public class Example
{
public static void Main ()
{
CancellationTokenSource cts = new CancellationTokenSource ();
var thread = new Thread (threadwork);
Thread. Start (CTS. Token);
while (true)
{
if (Console.readkey (). Keychar = = ' C ')
{
Console.WriteLine ("Request to cancel thread execution");
Cts. Cancel ();
Break
}
}
Console.ReadLine ();
}

private static void Threadwork (object state)
{
CancellationToken CancellationToken = (cancellationtoken) state;

while (true)
{
Check whether to cancel
if (cancellationtoken.iscancellationrequested)
{
Console.WriteLine ("Thread has been canceled");
Console.WriteLine ("The thread's resources have been cleaned up.) ");
Break
}
Simulation work
Thread.spinwait (500000);
Console.WriteLine ("I'm still working.") ");
}
}
}

unblock a blocked thread
In the example above, the background thread is calculated for a long time, but more often, the thread will go into a blocking state because it waits for an event. This time, in fact, the thread is no longer executing state, it is obvious that it does not have the opportunity to check the cancellation flag. So how do we solve this problem? The CancellationToken WaitHandle property provides a solution. The WaitHandle class has a static method waitany that can wait for multiple events at the same time, and when any one of the multiple events is valid, the thread will return from the blocking state. You can determine what event occurred based on the return value of the WaitAny method, thus executing the code accordingly. Example:
Copy Code code as follows:

public class Example
{
private static int Value;

public static void Main ()
{
var AutoResetEvent = new AutoResetEvent (false);
var cts = new CancellationTokenSource ();
var state = new {valueavailableevent = AutoResetEvent, CancellationToken = cts. Token};
var threadconsumer = new Thread (consumerthreadwork);
var threadproducter = new Thread (producterthreadwork);

Threadconsumer.start (state);
Threadproducter.start (state);

while (true)
{
if (Console.readkey (). Keychar = = ' C ')
{
Console.WriteLine ("Request to cancel thread execution");
Cts. Cancel ();
Break
}
}
Console.ReadLine ();

}
public static void Producterthreadwork (dynamic State)
{
var valueavailableevent = (AutoResetEvent) state. Valueavailableevent;
var CancellationToken = (CancellationToken) state. CancellationToken;
var rand = new Random ();
while (!cancellationtoken.iscancellationrequested)
{
Value = Rand. Next ();
Console.WriteLine ("\ r \ n produces a value of {0}", value);
Valueavailableevent.set ();
Thread.Sleep (500);
}

Console.WriteLine ("Producer thread was canceled.) ");
}

public static void Consumerthreadwork (dynamic State)
{
var valueavailableevent = (AutoResetEvent) state. Valueavailableevent;
var CancellationToken = (CancellationToken) state. CancellationToken;
var events = new[] {valueavailableevent, cancellationtoken.waithandle};

while (true)
{
var eventindex = WaitHandle.WaitAny (events);
Working with Data
if (eventindex = 0)
{
Console.WriteLine ("Processing value {0}.") ", Value);
}
Handling Cancellation Events
else if (Eventindex = 1)
{
Console.WriteLine ("Consumer thread is canceled.") ");
Break
}
}
}
}

In the example above, there are three threads, the UI thread, the producer thread and the consumer thread, respectively. Where the producer thread produces a valid number every second and saves the data to the Value field, and the consumer thread waits for the value to be generated, the wait process is blocked. The consumption thread passes the WaitHandle.WaitAny method to wait for the value valid event or cancels the event simultaneously, when any one event is valid, the thread will continue, and the event that occurs is judged by the value returned and processed accordingly.

Summary
The problem of threading cancellation in a multithreaded model is still more complex. The Thread.IsBackground property provides a way to automatically end a thread after the foreground thread ends. The Thread.Abort method provides a "rough" way to end a thread. The CancellationTokenSource class is the standard mode of threading cancellation, and we should use this pattern more. Article writing is not much, the basic word is not enough, the code to gather, the big guys will look at it.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.