Docker running background thread

Welcome back to .NET Core Central. Today I am going to pick up the application I build in the last blog: https://dotnetcorecentral.com/blog/docker-container-for-net-core/. I will update the application to demonstrate docker running background thread in a .NET Core console application.

Problem statement for Docker running a background thread

If we create a project which runs a background thread; and we keep the main thread alive using Console.ReadLine(), the docker container does not regard that. Meaning, when the .NET Core application runs in docker; and the runtime encounters the Console.ReadLine(), it just continues to execute forward. Instead of stopping for user input.

Background Thread

Firstly, I will create a new Task to run in the background inside of Main method. Secondly, inside of the Task callback, I will increment an integer and print it inside a while loop. Thirdly, I will pause the thread for a second, and continue.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace Docker.Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello Docker World!");
            var count = 0;

            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    Console.WriteLine($"Current Count {++count}");
                    Thread.Sleep(1000);
                }
            });

            Console.WriteLine("Press Ctrl + C to cancel!");
            Console.ReadLine();
        }
    }
}

Finally, I will run the docker command to create a docker image.

Note: The docker file will not change from my previous blog post: https://dotnetcorecentral.com/blog/docker-container-for-net-core/.

docker build -t dockerdemo -f DockerFile .

This will create a new image. And post that I will create a new container and start it.

docker create dockerdemo
docker start -i <container id or name>

Output in Docker

docker output

As you can see in the output; the container stopped after printing the first count.

The solution

I will add a AutoResetEvent object which will wait until it gets a signal. This will allow the application to run until it gets a signal. Finally, I will add an event handler for the Console.CancelKeyPress to close the console.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace Docker.Demo
{
    class Program
    {
        private static readonly AutoResetEvent _closingEvent = new AutoResetEvent(false);

        static void Main(string[] args)
        {
            Console.WriteLine("Hello Docker World!");
            var count = 0;

            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    Console.WriteLine($"Current Count {++count}");
                    Thread.Sleep(1000);
                }
            });

            Console.WriteLine("Press Ctrl + C to cancel!");
            Console.CancelKeyPress += ((s, a) =>
            {
                Console.WriteLine("Bye!");
                _closingEvent.Set();
            });

            _closingEvent.WaitOne();
        }
    }
}

Running the updated code

I will build the docker image once again with the updated change. Post that I will create a new container and start it in interactive mode.

docker running background thread

As you can see, now the application is running as intended inside the container. The background thread is continuously processing.

Conclusion

In conclusion, we can use a console application to run background thread in docker. We would need to use an event signaling to make that happen. Instead of using traditional Console.ReadLine mechanism.

The entire coding process is captured in the following YouTube video: https://youtu.be/UmS5DRHWmbI

Source code: https://github.com/choudhurynirjhar/docker-demo