Best way to terminate a thread
In general you have two options:
allow the thread to terminate itself. This covers your first option.
terminate the thread externally. This covers your other options.
And that's it. And none of them, in general, can prevent the threads from running for indefinite time after they should (from the programmer's intent point of view) terminate.
The most predictable approach is the first one. If terminating takes too long, try to do the processing in smaller steps to allow checking the termination flag more frequently. Also, note the IsBackground
flag which will help with the application being unable to close itself.
The whole problem with the other options is that any code (except for some special cases like finally
blocks) can be just interrupted in the middle of its execution, which can lead to some undesired results (e.g. some unmanaged resources not released) - as it is explained in Thread.Abort
documentation.
Note that the third approach in the newest versions of .NET framework is equivalent to calling the Abort
method on your executing threads, as explained in the documentation:
The threads in domain are terminated using the
Abort
method, which throws aThreadAbortException
in the thread. Although the thread should terminate promptly, it can continue executing for an unpredictable amount of time in a finally clause.
So it seems better to use Thread.Abort
from these two, as it's simpler and more readable.
If the first approach is problematic, and if you are well aware of the type of operations your thread is executing and there is no problem in interrupting them in-between then the "brutal" approach should be fine.
How to use thread.abort()
In case you have to use threads, try this. Otherwise, try cancelAsync like in this link:
https://www.wpf-tutorial.com/misc/cancelling-the-backgroundworker/
// We will set this true to notify the worker threads return.
private bool shouldAbort;
// when hitting submit set:
shouldAbort = false;
void MethodThatDoesWork()
{
//we should stop if required
if (shouldAbort)
{
state.Stop();
}
//code
}
we must be sure that all threads are terminated when the form is closed.
so we add these controls.
private void ItemsCopyer_FormClosing(object sender, FormClosingEventArgs e)
{
System.Diagnostics.Process.GetCurrentProcess().Kill();
}
private void btnAbort_Click(object sender, EventArgs e)
{
shouldAbort = true;
btnAbort.Enabled = false;
}
Revisiting Thread.Abort() - is it safe?
Thread.Abort
is a lot safer than it used to be for the following reasons.
- The runtime will defer aborts while execution is in unmanaged code.
- The abort will allow
finally
blocks to execute.
However, there is still a problem with exactly when the ThreadAbortException
gets injected. Consider this code.
public class Example
{
private DateTime value = DateTime.MinValue;
public void DoSomething()
{
try
{
value = DateTime.UtcNow;
}
finally
{
}
}
}
If this code were running on a 32-bit platform the value
variable could be corrupted if Thread.Abort
was called and the ThreadAbortException
were injected in the middle of the write to value
. Since DateTime
is 8 bytes the write has to take place using more than one instruction.
It is possible to guard against this by placing critical code in a finally
block and by using Constrained Execution Regions, but it would be incredibly difficult to get right for all but the simplest types your define. And even then you cannot just put everything in a finally
block.
Stop / abort a class-loop thread, C#
Your code if(myBool == false) {theadDraw.Abort();}
isn't working because you're checking this once, immediately after the thread starts. And it isn't ever checked again (threadDate.Start()'
isn't a blocking call).
But, NET Framework contains the CancellationToken
concept which is used to cancel asynchronous code.
// Step 1, create a cancellation token:
CancellationTokenSource cancel = new CancellationTokenSource();
// Step 2, reference the token from inside your thread
void ThreadStartMethod() {
while (!cancel.IsCancellationRequested) {
// Do work ...
}
}
// Step 3, cancel the token when you need to
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space)
cancel.Cancel();
}
Note: make sure you re-create the cancellation token whenever you start the thread
How to abort a Task like aborting a Thread (Thread.Abort method)?
- You shouldn't use Thread.Abort()
- Tasks can be Cancelled but not aborted.
The Thread.Abort() method is (severely) deprecated.
Both Threads and Tasks should cooperate when being stopped, otherwise you run the risk of leaving the system in a unstable/undefined state.
If you do need to run a Process and kill it from the outside, the only safe option is to run it in a separate AppDomain.
This answer is about .net 3.5 and earlier.
Thread-abort handling has been improved since then, a.o. by changing the way finally blocks work.
But Thread.Abort is still a suspect solution that you should always try to avoid.
And in .net Core (.net 5+) Thread.Abort() will now throw a PlatformNotSupportedException
.
Kind of underscoring the 'deprecated' point.
How to terminate a thread in C#?
Thread.Abort
will "kill" the thread, but this is roughly equivalent to:
Scenario: You want to turn off your computer
Solution: You strap dynamite to your computer, light it, and run.
It's FAR better to trigger an "exit condition", either via CancellationTokenSource.Cancel
, setting some (safely accessed) "is running" bool, etc., and calling Thread.Join
. This is more like:
Scenario: You want to turn off your computer
Solution: You click start, shut down, and wait until the computer powers down.
Related Topics
Not Ableto Serialize Dictionary with Complex Key Using JSON.Net
How to Connect to an Mdf Database File
How Big Is an Object Reference in .Net
Why Does "Int[] Is Uint[] == True" in C#
Why Is the 'This' Keyword Required to Call an Extension Method from Within the Extended Class
What Does "Where T:Class, New()" Mean
.Net Xml Serialization Gotchas
How to Implement a Never Ending Task. (Timers VS Task)
C# Rsa Encryption/Decryption with Transmission
The Type of One of the Expressions in the Join Clause Is Incorrect in Entity Framework
Generic Method Executed with a Runtime Type
How to Execute Code That Is in a String
Xml-Selectnodes with Default-Namespace via Xmlnamespacemanager Not Working as Expected
Deserializing JSON with Unknown Object Names
How to Use the Ternary Operator Inside an Interpolated String