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
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.
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