How to abort a task completely silently in C# - c#

I have code that looks like this:
private void DoWork() {
try
{
MakeCallToServiceWhichCreatesResource();
UpdateState()
}
catch (Exception e)
{
UpdateState()
}
}
However, there was an issue where when our service had a deployment, it killed threads instantly, without an exception. So the thread was killed in the middle of making a call to the service, which created an issue because the resource that the service call generated was not updated in state, and thus became dangling and wasn't recoverable. I then made a fix to the following:
private void DoWork() {
try
{
UpdateStateWithOutputInAnticipationOfServiceCall()
MakeCallToServiceWhichCreatesResource();
}
catch (Exception e)
{
UpdateStateToRemoveOutput()
}
}
This would solve the issue of a thread being killed while the call is being made because the resource could be deleted later (and if the external service call failed, making an unnecessary delete call is acceptable). However, I am looking to add a unit test for this scenario now, but I'm not sure how to simulate total thread obliteration. Using Thread abort doesn't seem to work because it would throw an exception rather than kill immediately, but environment failfast wouldn't seem to work because it would kill the unit test environment as far as I can tell. Any ideas on how to build a unit test that can nuke a thread that runs the code?

Regarding how to abort a thread, either silently or loudly, you can take a look at this question. Spoiler alert, neither is possible in the latest .NET platform. If you feel sad about it, you might feel better by learning that the death of Thread.Abort is definitive and irreversible:
Thread.Abort for production scenarios is not going to come back to .NET Core. I am sorry.
Regarding how to improve your code, I would suggest familiarizing yourself with the finally keyword. It helps significantly at simplifying and robustifying the disposal of resources:
private void DoWork()
{
try
{
MakeCallToServiceWhichCreatesResource();
}
finally
{
UpdateState();
}
}
Regarding how to prevent your threads from dying silently, one idea is to avoid suppressing the errors in the catch block. The throw is your friend:
private void DoWork()
{
try
{
MakeCallToServiceWhichCreatesResource();
UpdateState();
}
catch (Exception ex)
{
UpdateState();
throw;
}
}
Now your threads will die loudly, taking down the process with them. This might not be what you want.
One way to find a balance between dying with screams and agony, and dying in total silence, is to use tasks instead of threads. You can offload the DoWork call to the ThreadPool with the Task.Run method, and you'll get back a Task object that represents the result of the execution. You can store this task in a field or in a list of tasks, and periodically inspect its properties like the Status, IsCompleted, IsFaulted, Exception etc to know how is doing. You can also attach continuations to it (ContinueWith), in order to log its completion or whatever. Or you can await it, if you are familiar with async and await. The best part is that if your task fails, the thread on which it runs will not die with it. The thread will return to the ThreadPool, and will be available for future Task.Runs or other work.
Task workTask = Task.Run(() => DoWork());

Related

When my .NET code returned a Task, it wasn't doing the expected outcome. Changing it to async/await, fixed it. Why?

I have some pretty stock standard code for a typical .NET Core 2+ program.cs. I'm mainly setting up Logging.
With the code below, it's not async/await and the following happens:
Logging occurs during the startup process 100%.
the CloseAndFlush(); occurs nearly instantly, before the rest of the app does stuff.
No logging occurs in any controllers.
This is in part due to how Serilog works but that's not really the important bit, AFAIK.
The code steps right over return CreateWebHostBuilder(args).Build().RunAsync(); .. when I thought this is the part where it would be awaited by the caller? When I debug my app, it does await (hang) on that line ... until the app has completed starting up. Once it's ready to accept connections, it then returns back here ... and runs through .. which means it calls Log.CloseAndFlush() and then return Task.CompletedTask.
Buggy Code:
public static Task Main(string[] args)
{
Log.Logger = new LoggerConfiguration()....CreateLogger();
try
{
// awaits here until the app has 100% started, then continues.
return CreateWebHostBuilder(args).Build().RunAsync();
}
catch (Exception exception)
{
Log.Logger.Fatal(exception, "Host terminated unexpectantly. Sadness :~(");
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
Log.CloseAndFlush();
}
return Task.CompletedTask;
}
Now changing this to async/await fixes everything. The code does correctly await on return CreateWebHostBuilder(args).Build().RunAsync(); .. and then the CloseAndFlush() is called when the app is closing/terminating.
public static async Task Main<T>(string[] args) where T : class
{
Log.Logger = new LoggerConfiguration()....CreateLogger();
try
{
// Correctly waits here until the app explodes or ctrl-c has been pressed.
await CreateWebHostBuilder<T>(args).Build().RunAsync();
}
catch (Exception exception)
{
Log.Error(exception, "Stopped program because of an exception.");
}
Log.Debug("Finished shutting down app.");
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
Log.CloseAndFlush();
}
Would returning a Task probably be only suitable if the method is only doing one async/await in it AND that is the last thing in the method?
Returning a Task1 instead of awaiting it is your way of saying "there's nothing left for this method to do here"2.
If that's not the case (as here, where you don't want your finally clause to run yet), you're not done. You need some way of running some code at a later point in time, but you've got nothing useful to do now. And that's precisely what await allows you to signal.
1As Jonas mentions, this is exactly true for non-Task returns too.
2I'm ignoring the case when you take a Task from elsewhere, add a ContinueWith and return the resulting Task, because there you're using a different mechanism to ensure you get to run code later and it's not precisely "this method" that runs in the continuation.
Would returning a Task probably be only suitable if the method is only doing one async/await in it AND that is the last thing in the method?
Basically, yes. Returning the task as in your first snippet will let the finally block run as you leave the scope, just like any other return statement inside a try with an associated finally. And as commented by ckuri your catch block won't do what you want either, as it will not catch exceptions from the task, only from the setup in CreateWebHostBuilder itself.

call method from another thread without blocking the thread (or write custom SynchronizationContext for non-UI thread) C#

This is probably one of the most frequent questions in the Stackoverflow, however I couldn't find the exact answer to my question:
I would like to design a pattern, which allows to start thread B from thread A and under specific condition (for example when exception occurs) call the method in thread A. In case of exception the correct thread matters a lot because the exception must call a catch method in the main thread A. If a thread A is an UI thread then everything is simple (call .Invoke() or .BeginInvoke() and that's it). The UI thread has some mechanism how it is done and I would like to get some insights how it would be possible to write my own mechanism for the non-UI thread. The commonly suggested method to achieve this is using the message pumping http://www.codeproject.com/Articles/32113/Understanding-SynchronizationContext-Part-II
but the while loop would block the thread A and this is not what I need and not the way how UI thread handles this issue. There are multiple ways to work around this issue but I would like to get a deeper understanding of the issue and write my own generic utility independently of the chosen methods like using System.Threading.Thread or System.Threading.Tasks.Task or BackgroundWorker or anything else and independently if there is a UI thread or not (e.g. Console application).
Below is the example code, which I try to use for testing the catching of the exception (which clearly indicates the wrong thread an exception is thrown to). I will use it as an utility with all the locking features, checking if a thread is running, etc. that is why I create an instance of a class.
class Program
{
static void Main(string[] args)
{
CustomThreads t = new CustomThreads();
try
{
// finally is called after the first action
t.RunCustomTask(ForceException, ThrowException); // Runs the ForceException and in a catch calls the ThrowException
// finally is never reached due to the unhandled Exception
t.RunCustomThread(ForceException, ThrowException);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
// well, this is a lie but it is just an indication that thread B was called
Console.WriteLine("DONE, press any key");
Console.ReadKey();
}
private static void ThrowException(Exception ex)
{
throw new Exception(ex.Message, ex);
}
static void ForceException()
{
throw new Exception("Exception thrown");
}
}
public class CustomThreads
{
public void RunCustomTask(Action action, Action<Exception> action_on_exception)
{
Task.Factory.StartNew(() => PerformAction(action, action_on_exception));
}
public void RunCustomThread(Action action, Action<Exception> action_on_exception)
{
new Thread(() => PerformAction(action, action_on_exception)).Start();
}
private void PerformAction(Action action, Action<Exception> action_on_exception)
{
try
{
action();
}
catch (Exception ex)
{
action_on_exception.Invoke(ex);
}
finally
{
Console.WriteLine("Finally is called");
}
}
}
One more interesting feature that I've found is that new Thread() throws unhandled Exception and finally is never called whereas new Task() does not, and finally is called. Maybe someone could comment on the reason of this difference.
and not the way how UI thread handles this issue
That is not accurate, it is exactly how a UI thread handles it. The message loop is the general solution to the producer-consumer problem. Where in a typical Windows program, the operating system as well as other processes produce messages and the one-and-only UI thread consumes.
This pattern is required to deal with code that is fundamentally thread-unsafe. And there always is a lot of unsafe code around, the more convoluted it gets the lower the odds that it can be made thread-safe. Something you can see in .NET, there are very few classes that are thread-safe by design. Something as simple is a List<> is not thread-safe and it up to you to use the lock keyword to keep it safe. GUI code is drastically non-safe and no amount of locking is going to make it safe.
Not just because it is hard to figure out where to put the lock statement, there is a bunch of code involved that you did not write. Like message hooks, UI automation, programs that put objects on the clipboard that you paste, drag and drop, shell extensions that run when you use a shell dialog like OpenFileDialog. All of that code is thread-unsafe, primarily because its author did not have to make it thread-safe. If you trip a threading bug in such code then you do not have a phone number to call and a completely unsolvable problem.
Making a method call run on a specific thread requires this kind of help. It is not possible to arbitrarily interrupt the thread from whatever it is doing and force it to call a method. That causes horrible and completely undebuggable re-entrancy problems. Like the kind of problems caused by DoEvents(), but multiplied by a thousand. When code enters the dispatcher loop then it is implicitly "idle" and not busy executing its own code. So can take an execution request from the message queue. This can still go wrong, you'll shoot your leg off when you pump when you are not idle. Which is why DoEvents() is so dangerous.
So no shortcuts here, you really do need to deal with that while() loop. That it is possible to do so is something you have pretty solid proof for, the UI thread does it pretty well. Consider creating your own.

C# - Thread Abort Exception (Thread Abort Exception) rethrowing itself

I have the current code:
class Program
{
private static void Main()
{
while (true)
{
try
{
Thread.CurrentThread.Abort();
}
catch (ThreadAbortException)
{
Console.WriteLine("Abort!");
Thread.ResetAbort();
}
Console.WriteLine("now waiting");
Console.ReadKey();
}
}
}
Now I know the method ResetAbort is supposed to prevent the ThreadAbortException from continue to re-throw itself even when a catch statement is catching it, but my question is this:
If anyone can use the ResetAbort method, then what's the point of the exception specially re-throw itself?
the user can just do
catch (ThreadAbortException ex)
{
Console.WriteLine("Abort!");
throw ex;
}
Thread.ResetAbort() is not meant for common use. It can cause undesired behavior if you don't understand why the thead abort happened. Because of this, and probably to make ASP.NETs stable in shared hosting environments, the SecurityPermissionFlag.ControlThread permission is required to call Thread.ResetAbort()
MSDN Link
The point of ThreadAbortException rethrowing itself is to make sure the thread terminates unless the user explicitly calls ResetAbort.
Let me explain:
try
{
// ... Thread abort happens somewhere in here
}
catch (Exception ex)
{
_log.Error(ex);
}
Here you have a typical example of code that ensures no exception propagates from inside the try block. I know that catching Exception is bad practice, but code like this exists nonetheless.
If you call Abort while the thread is inside the try block you still want it to abort. You just can't rely on users writing this sort of code everywhere:
try
{
// ... Thread abort happens somewhere in here
}
catch (ThreadAbortException)
{
throw; // No, you'll NEVER see code like this in real life
}
catch (Exception ex)
{
_log.Error(ex);
}
So, in order to provide a sort of reliable Abort, the exception has to be automatically rethrown, or it may easily get discarded by accident.
ResetAbort is meant for the very rare case when you specifically detect a thread abort, and you exactly know why it happenned, and you want to prevent it.
Needless to say, the use cases for this are extremely rare. Thread aborts are treated by the runtime in a very special way, and you should avoid them whenever possible. Heck, they even aren't reliable as you pointed out, and all this discussion is ignoring CERs which make matters worse.
The point is to define a default behavior in which the exception is rethrown, seeing as how there is a remote chance that the user will have any point of continuing the thread.
Moreover, ResetAbort has a security demand and can not be called by any code.
Because Aborting a thread doesn't necessarily mean an exception will be thrown. For the Abort Procedure the catch (ThreadAbortException) block is just another critical region of code. It only gives us a thread safe and convenient way of detecting if the current thread is being aborted (and maybe with some state being passed too) in case we want to do something special. Other than that, it is like any other critical region (like a finally block) where it will terminate the thread after its execution.
At the same time, in your example Abort is called synchronously (which is actually safe to do) and in that case it is very similar to throwing an exception. Things only get interesting and dangerous when it's called asynchronously from another thread, due to the Abort procedure being more complicated than just throwing an exception: In essence, first, thread is marked as being aborted, then critical code regions (for example finally blocks) are executed and only then the exception is thrown, if the AbortRequested flag is still set on the thread, and so on.
Code below illustrates this fact by recovering an aborted thread without catching any exceptions:
var inFinally = new ManualResetEvent(false);
var abortCalled = new ManualResetEvent(false);
var t = new Thread(_ =>
{
Console.WriteLine("Thread started..");
try
{
}
finally
{
inFinally.Set();
abortCalled.WaitOne();
Console.WriteLine(" ThreadState (before): " + Thread.CurrentThread.ThreadState);
// This isn't thread safe, and ugly?
if ((Thread.CurrentThread.ThreadState & ThreadState.AbortRequested) != 0)
{
Thread.ResetAbort();
}
Console.WriteLine(" ThreadState (after): " + Thread.CurrentThread.ThreadState);
}
Console.WriteLine("Executed because we called Thread.ResetAbort()");
});
t.Start();
inFinally.WaitOne();
// Call from another thread because Abort()
// blocks while in finally block
ThreadPool.QueueUserWorkItem(_ => t.Abort());
while ((t.ThreadState & ThreadState.AbortRequested) == 0)
{
Thread.Sleep(1);
}
abortCalled.Set();
Console.ReadLine();
// Output:
//--------------------------------------------------
// Thread started..
// ThreadState (before): AbortRequested
// ThreadState (after): Running
// Executed because we called Thread.ResetAbort()
Now, I must be honest: I am not entirely sure how one could use this feature and create something useful. But it sounds like Thread.Abort API was (probably still is, I don't know) used to facilitate thread and AppDomain reuse in frameworks like ASP.NET.
In one of Joe Duffy's Blog entries, Managed code and asynchronous exception hardening, he talks about ResetAbort and the Abort API:
Some framework infrastructure, most notably ASP.NET, even aborts individual threads
routinely without unloading the domain. They backstop the ThreadAbortExceptions, call
ResetAbort on the thread and reuse it or return it to the CLR ThreadPool.
I can imagine it can be used in a framework to reuse the managed threads, reducing the overhead. However, the problems (bad thread synchronization design, bad exception handling, dead locks and so on) introduced in user code, by this easily misunderstood API, rendered the Abort and ResetAbort calls more troublesome than useful.

How to terminate a thread when the worker can't check the termination string

I have the following code running in a Windows form. The method it is calling takes about 40 seconds to complete, and I need to allow the user the ability to click an 'Abort' button to stop the thread running.
Normally I would have the Worker() method polling to see if the _terminationMessage was set to "Stop" but I can't do this here because the long running method, ThisMethodMightReturnSomethingAndICantChangeIt() is out of my control.
How do I implement this user feature please ?
Here is my thread code.
private const string TerminationValue = "Stop";
private volatile string _terminationMessage;
private bool RunThread()
{
try
{
var worker = new Thread(Worker);
_terminationMessage = "carry on";
_successful = false;
worker.Start();
worker.Join();
finally
{
return _successful;
}
}
private void Worker()
{
ThisMethodMightReturnSomethingAndICantChangeIt();
_successful = true;
}
Well, the simple answer would be "you can't". There's no real thread abort that you can use to cancel any processing that's happenning.
Thread.Abort will allow you to abort a managed thread, running managed code at the moment, but it's really just a bad idea. It's very easy to end up in an inconsistent state just because you were just now running a singleton constructor or something. In the end, there's quite a big chance you're going to blow something up.
A bit orthogonal to the question, but why are you still using threading code like this? Writing multi-threaded code is really hard, so you want to use as many high-level features as you can. The complexity can easily be seen already in your small snippet of code - you're Joining the newly created thread, which means that you're basically gaining no benefit whatsoever from starting the Worker method on a new thread - you start it, and then you just wait. It's just like calling Worker outright, except you'll save an unnecessary thread.
try will not catch exceptions that pop up in a separate thread. So any exception that gets thrown inside of Worker will simply kill your whole process. Not good.
The only way to implement reliable cancellation is through cooperative aborts. .NET has great constructs for this since 4.0, CancellationToken. It's easy to use, it's thread-safe (unlike your solution), and it can be propagated through all the method chain so that you can implement cancellation at depth. Sadly, if you simply can't modify the ThisMethodMightReturnSomethingAndICantChangeIt method, you're out of luck.
The only "supported" "cancellation" pattern that just works is Process.Kill. You'd have to launch the processing method in a wholy separate process, not just a separate thread. That can be killed, and it will not hurt your own process. Of course, it means you have to separate that call into a new process - that's usually quite tricky, and it's not a very good design (though it seems like you have little choice).
So if the method doesn't support some form of cancellation, just treat it like so. It can't be aborted, period. Any way that does abort it is a dirty hack.
Well, here's my solution so far. I will definitely read up on newer .NET higher level features as you suggest. Thanks for the pointers in the right direction
private void RunThread()
{
try
{
var worker = new Thread(Worker);
SetFormEnabledStatus(false);
_usuccessful = false;
worker.Start();
// give up if no response before timeout
worker.Join(60000); // TODO - Add timeout to config
worker.Abort();
}
finally
{
SetFormEnabledStatus(true);
}
}
private void Worker()
{
try
{
_successful= false;
ThisMethodMightReturnSomethingAndICantChangeIt();
_successful = true;
}
catch (ThreadAbortException ex)
{
// nlog.....
}
catch (Exception ex)
{
// nlog...
}
}

TryTake Performance on blockingcollection

I have a programm which sometimes runs significantly slow.
I tried Teleriks Justtrace to find out, what could possible cause a hang of the application.
A non UI thread (therefore I believe it's not really the cause of the hang) does assync. get objects (Enqueues workitems) and deques it to do some work.
Enqueue:
public void EnqueueObject(WorkUnit workunit)
{
try
{
workUnits.Add(workunit);
}
catch (Exception ex)
{
/handle exception
}
}
Dequeue:
public WorkUnit Dequeue()
{
try
{
WorkUnit aWorkUnit = null;
workUnits.TryTake(out aWorkUnit, 1000);
return aWorkUnit ;
}
catch (InvalidOperationException ex)
{
//
}
return null;
}
TryTake was used to check for an abort of current work (instead of the BlockingCollection Complete method which just throws some errors when called - i don't want to use errors for programm flow)
Call to dequeue:
while(!isStopped)
{
ProcessWorkItem(Dequeue());
}
Up to here it looks quite simple.
The problem is, that Teleriks JustTrace shows, that the line "workUnits.TryTake(out aWorkUnit, 1000);" takes 30% of the total execution time of the program.
How can this be?
With more details it shows that inside the TryTake System.Threading.Monitor.Wait takes up all the time - i thought the Wait would send a thread to sleep, so it does not consume something during the wait. Where is the error in the thought?
You can try using workUnits.TryTake(out aWorkUnit) without the timeout parameter. And then, you should modify while loop to look similar to this:
while(!isStopped)
{
WorkUnit wu = Dequeue();
if(wu != null)
ProcessWorkItem(wu);
else
Thread.Sleep(40);
}
Also, if you are running this code on a UI thread it will make your UI unresponsive. You should use for example BackgroundWorker for the operation. Here's the description of BackgroundWorker class from MSDN documentation:
The BackgroundWorker class allows you to run an operation on a separate, dedicated thread. Time-consuming operations like downloads and database transactions can cause your user interface (UI) to seem as though it has stopped responding while they are running. When you want a responsive UI and you are faced with long delays associated with such operations, the BackgroundWorker class provides a convenient solution.

Categories

Resources