Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why are CancellationTokens not working if local methods are used?

Given the following code you would expect that the DoWait method is executed for one second in both cases. However, it works for the first case but hangs for the second.

If we add async/await to the local method the behavior is as expected.

Given that that CTs are structs and hence passed around by value, not reference, can anyone explain explain what’s going on?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

using System.Diagnostics;

namespace ConsoleApp2
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            //not using local method
            using var cts1 = new CancellationTokenSource(TimeSpan.FromSeconds(1));
            Console.WriteLine(await DoWait(cts1.Token));

            //using a local method
            Task<long> LocalMehtod()
            {
                using var cts1 = new CancellationTokenSource(TimeSpan.FromSeconds(1));
                return DoWait(cts1.Token);
            }

            Console.WriteLine(await LocalMehtod());
        }

        static async Task<long> DoWait(CancellationToken ct)
        {
            var stopwatch = Stopwatch.StartNew();
            var elapsedMilliseconds = stopwatch.ElapsedMilliseconds;

            try
            {
                while (true)
                {
                    elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
                    ct.ThrowIfCancellationRequested();
                    await Task.Delay(10);
                }
            }
            catch (OperationCanceledException) { }
            return elapsedMilliseconds;
        }
    }
}

>Solution :

The CancellationTokenSource you’re creating within LocalMehtod is being disposed when that method returns. Since it’s disposed, it can no longer cancel the token you already passed to DoWait.

In the version where you make the local method async/await, it doesn’t get disposed, so can carry on working as expected.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading