Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I make an exception in Task.Run crash the program?

Tags:

.net

.net-4.5

I'm not a big fan of quietly swallowed exceptions, but the following code does exactly that:

Task.Run(() =>
{
    var obj = DoSomethingCpuIntensive(); // returns null, due to a bug
    obj.DoMoreStuff();
    Console.WriteLine("after"); // never get here; program continues running
});

I've read about the ThrowUnobservedTaskExceptions configuration value, but this doesn't help, since I never do anything with the Task returned (edit: actually it does help, but only in Release builds).

Is there a way to make that unhandled exception crash the program? Am I using Task.Run in a way I'm not supposed to?

like image 708
Roman Starkov Avatar asked Oct 21 '22 11:10

Roman Starkov


2 Answers

I strongly recommend you use Task.Run over ThreadPool.QueueUserWorkItem.

First, take a step back. What's the purpose of DoSomethingCpuIntensive? If you're calculating some value, I suggest you return it, so you have a Task<T> instead of a Task. e.g., (assuming DoMoreStuff is not CPU intensive):

async Task DoWorkAsync()
{
  var obj = await Task.Run(() => DoSomethingCpuIntensive());
  obj.DoMoreStuff();
}

The idea I'm trying to get across is that your code should care about the results of your background operations, even if the "result" is just "success" or "exception". Your code is cleaner that way. Otherwise, you've got a semi-independent system that you can only respond to by detecting changes in your application state. Much more messy.

That said, if you really do want to have the semi-independent system and you want it to crash your process if it fails, then ThrowUnobservedTaskExceptions is exactly what you want. I'm not sure why you think it wouldn't help.

like image 63
Stephen Cleary Avatar answered Oct 30 '22 02:10

Stephen Cleary


It appears that using Task.Run like this is, indeed, a mistake. I think I'm supposed to await it, else silly things like the above will happen.

When it does crash with the await, the debugger is rather unhelpful, looking like this:

                enter image description here

I take this all to mean I'm really doing the wrong thing with Task.Run here.

A simple fix is use the good old ThreadPool.QueueUserWorkItem instead:

                  enter image description here

That's much better! I didn't really need async/await in this code anyway; I just used Task.Run because it's less typing.

like image 31
Roman Starkov Avatar answered Oct 30 '22 02:10

Roman Starkov