Implementing Tasks, await and async for background work

128 Views Asked by At

I am new to Tasks and its associated keywords in C#. My goal is to setup a background thread/task that will continuously poll a server every n seconds. Using the .NET TPL library, is the following structure of methods and fields an appropriate way to accomplish this?

    private CancellationTokenSource _cts;
    private CancellationToken _ct;

    public override async Task StartSomeServiceAsync()
    {
        _cts = new CancellationTokenSource();
        _ct = _cts.Token;

        await Task.Run(() => this.Work(_ct));
        
        //TODO Do some reporting, system management/cleanup etc... 
          after the task has been cancelled
    }

    protected override void Work(CancellationToken ct)
    {        
        while (true)
        {
            if (ct.IsCancellationRequested)
                break;

            Thread.Sleep(5000);
            //Make network calls, collect data
            //Notify data subscribers of new data received from network
        }
    }

    public override void StopSomeService()
    {
        _cts.Cancel();
    }

The owning object of this code can either start this background work using a StartSomeServiceAsync() call, and if external conditions are met, then it would stop the background thread/task by cancelling the task via a StopSomeService() call.

Any input is greatly appreciated, thank you for your time.

1

There are 1 best solutions below

0
On

You are using a ThreadPool thread for long running work. This is not the intended usage of the ThreadPool. Instead of the Task.Run, it is preferable to use a dedicated thread by using the advanced Task.Factory.StartNew API with the LongRunning option:

await Task.Factory.StartNew(() => this.Work(_ct), CancellationToken.None,
    TaskCreationOptions.LongRunning, TaskScheduler.Default);

Instead of dedicating a thread and blocking it with Thread.Sleep(5000);, you could also use a timer, like the System.Threading.Timer or the async-enabled PeriodicTimer. Nevertheless the dedicated thread has the advantage that it will tick consistently every 5 seconds. The built-in timers depend heavily on the ThreadPool, so they might tick inconsistently in case the ThreadPool happens to be saturated for prolonged time spans.