Why does JsonConvert.SerializeObject fail when called from a nested task?

Viewed 59

I have a console program which starts a long running task, which in turn starts 4 x long running tasks. By long running I mean all these tasks are supposed to run indefinitely.

However, calling JsonConvert.Serialize from any of the nested tasks crashes the app silently, without any error messages.

I've recreated this behaviour with a simple console program:

public class TestClass
{
    public string ATestProperty { get; set; }
}

internal class Program
{
    static void Main(string[] args)
    {            
        var outerTask = Task.Factory.StartNew(() =>
        {
            var nestedTask = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Inside nestedTask");
                var testClass = new TestClass { ATestProperty = "Hi from test class" };
                var serialisedClass = JsonConvert.SerializeObject(testClass);
                Console.WriteLine(serialisedClass);
            });
        });
        
        Console.WriteLine("DONE");
    }
}

This prints

DONE
Inside nestedTask

If I debug and step through the code, the program terminates right after executing

var serialisedClass = JsonConvert.SerializeObject(testClass);

I'm not sure what I'm missing, perhaps it is a combination of a task + serialisation behaviour that I'm not aware of. I've tried System.Text.Json to serialise my data too with the same results.

1 Answers
You can add Task.WaitAll(Task task) after each block of nested task.

Example:

 var outerTask = Task.Factory.StartNew(() =>
        {
            var nestedTask = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Inside nestedTask");
                var testClass = new TestClass { ATestProperty = "Hi from test class" };
                var serialisedClass = JsonConvert.SerializeObject(testClass);
                Console.WriteLine(serialisedClass);
            });
            Task.WaitAll(nestedTask);
            
        });
        Task.WaitAll(outerTask);
        
        Console.WriteLine("DONE");
Related