Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task.Delay(Timeout.Infinite, cancellationToken) does not return when cancellation is requested #88044

Closed
dav1dev opened this issue Jun 23, 2023 · 6 comments

Comments

@dav1dev
Copy link

dav1dev commented Jun 23, 2023

Describe the bug

The method call await Task.Delay(Timeout.Infinite, cancellationToken); does not behave as expected.
I expect this task to complete when cancellation is requested. But it does never return.

To Reproduce

public class Repro
{
        [Fact]
        public async Task TaskDelay_Infinite_DoesNotReturnWhenCancelled()
        {
            var ctsTest = new CancellationTokenSource(TimeSpan.FromSeconds(5));
            var ctsInfinite = new CancellationTokenSource();
            var started = new ManualResetEventSlim();
            var done = new ManualResetEventSlim();
            var t1 = Task.Run(async () =>
                {
                    started.Set();
                    // >> wait for cancellation
                    await Task.Delay(Timeout.Infinite, ctsInfinite.Token);
                    done.Set();
                },
                ctsTest.Token);

            started.Wait(ctsTest.Token);
            AssertIsTrue(started.IsSet);
            AssertIsFalse(done.IsSet);

            await Task.Delay(100, ctsTest.Token);

            AssertIsFalse(done.IsSet);

           // >> request cancellation now
            ctsInfinite.Cancel();

            await Task.Delay(100, ctsTest.Token);

            try
            {
                // >> would expect delay to return after cancellation
                done.Wait(ctsTest.Token);
            }
            catch (OperationCanceledException)
            {
                throw new Exception("Reset event was not set as expected because Task.Delay never returned");
            }

            await t1.WaitAsync(ctsTest.Token);
            AssertIsTrue(t1.IsCompleted);
        }

        private static void AssertIsTrue(bool value)
        {
            if (!value)
            {
                throw new Exception("Expected value to be true but was false.");
            }
        }

        private static void AssertIsFalse(bool value)
        {
            if (value)
            {
                throw new Exception("Expected value to be false but was true.");
            }
        }
}

Exceptions (if any)

Task is hanging forever (starvation).

Further technical details

dotnet --info

.NET SDK: Version: 7.0.304 Commit: 7e794e2806

Runtime Environment:
OS Name: Windows
OS Version: 10.0.19045
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\7.0.304\

Host:
Version: 7.0.7
Architecture: x64
Commit: 5b20af4

.NET SDKs installed:
6.0.410 [C:\Program Files\dotnet\sdk]
7.0.304 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.18 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.18 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.18 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
Not set

global.json file:
Not found

Learn more:
https://aka.ms/dotnet/info

Download .NET:
https://aka.ms/dotnet/download

.NET SDK (reflecting any global.json):
Version: 6.0.410
Commit: 28c7c894a3

Runtime Environment:
OS Name: Windows
OS Version: 10.0.19045
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\6.0.410\

Host:
Version: 7.0.7
Architecture: x64
Commit: 5b20af4

.NET SDKs installed:
6.0.410 [C:\Program Files\dotnet\sdk]
7.0.304 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.18 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.18 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.18 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
Not set

global.json file:
C:\work\ECU300\global.json

Learn more:
https://aka.ms/dotnet/info

Download .NET:
https://aka.ms/dotnet/download

IDE

JetBrains Rider 2023.1.2 Build #RD-231.9011.39, built on May 17, 2023 Runtime version: 17.0.6+10-b829.9 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Windows 10.0 .NET 7.0.2 (Server GC) GC: G1 Young Generation, G1 Old Generation Memory: 1500M Cores: 32 Non-Bundled Plugins: com.layoutmanager (1.4.0) com.4lex4.intellij.solarized (2.4.0) Abc.MoqComplete.Rider (2023.1.0.1) idea.plugin.protoeditor (231.8109.91) com.intellij.resharper.StructuredLogging (2023.1.0.296) com.intellij.resharper.azure (3.50.0.1595-2023.1)

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Jun 23, 2023
@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@KalleOlaviNiemitalo
Copy link

// >> wait for cancellation
await Task.Delay(Timeout.Infinite, ctsInfinite.Token);
done.Set();

When ctsInfinite.Token is signalled, I expect that the task returned by Task.Delay should be cancelled and await should throw a TaskCanceledException, which would then prevent done.Set() from being executed.

Have you tried with a trycatch around the await? Alternatively, delete the done.Wait(ctsTest.Token) call and catch the OperationCanceledException from await t1.WaitAsync(ctsTest.Token) instead.

@KalleOlaviNiemitalo
Copy link

In .NET 8, ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing) could also work here. #22144

@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jun 26, 2023
@danmoseley danmoseley transferred this issue from dotnet/sdk Jun 26, 2023
@danmoseley danmoseley added area-System.Threading.Tasks and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jun 26, 2023
@ghost
Copy link

ghost commented Jun 26, 2023

Tagging subscribers to this area: @dotnet/area-system-threading-tasks
See info in area-owners.md if you want to be subscribed.

Issue Details

Describe the bug

The method call await Task.Delay(Timeout.Infinite, cancellationToken); does not behave as expected.
I expect this task to complete when cancellation is requested. But it does never return.

To Reproduce

public class Repro
{
        [Fact]
        public async Task TaskDelay_Infinite_DoesNotReturnWhenCancelled()
        {
            var ctsTest = new CancellationTokenSource(TimeSpan.FromSeconds(5));
            var ctsInfinite = new CancellationTokenSource();
            var started = new ManualResetEventSlim();
            var done = new ManualResetEventSlim();
            var t1 = Task.Run(async () =>
                {
                    started.Set();
                    // >> wait for cancellation
                    await Task.Delay(Timeout.Infinite, ctsInfinite.Token);
                    done.Set();
                },
                ctsTest.Token);

            started.Wait(ctsTest.Token);
            AssertIsTrue(started.IsSet);
            AssertIsFalse(done.IsSet);

            await Task.Delay(100, ctsTest.Token);

            AssertIsFalse(done.IsSet);

           // >> request cancellation now
            ctsInfinite.Cancel();

            await Task.Delay(100, ctsTest.Token);

            try
            {
                // >> would expect delay to return after cancellation
                done.Wait(ctsTest.Token);
            }
            catch (OperationCanceledException)
            {
                throw new Exception("Reset event was not set as expected because Task.Delay never returned");
            }

            await t1.WaitAsync(ctsTest.Token);
            AssertIsTrue(t1.IsCompleted);
        }

        private static void AssertIsTrue(bool value)
        {
            if (!value)
            {
                throw new Exception("Expected value to be true but was false.");
            }
        }

        private static void AssertIsFalse(bool value)
        {
            if (value)
            {
                throw new Exception("Expected value to be false but was true.");
            }
        }
}

Exceptions (if any)

Task is hanging forever (starvation).

Further technical details

dotnet --info

.NET SDK: Version: 7.0.304 Commit: 7e794e2806

Runtime Environment:
OS Name: Windows
OS Version: 10.0.19045
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\7.0.304\

Host:
Version: 7.0.7
Architecture: x64
Commit: 5b20af4

.NET SDKs installed:
6.0.410 [C:\Program Files\dotnet\sdk]
7.0.304 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.18 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.18 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.18 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
Not set

global.json file:
Not found

Learn more:
https://aka.ms/dotnet/info

Download .NET:
https://aka.ms/dotnet/download

.NET SDK (reflecting any global.json):
Version: 6.0.410
Commit: 28c7c894a3

Runtime Environment:
OS Name: Windows
OS Version: 10.0.19045
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\6.0.410\

Host:
Version: 7.0.7
Architecture: x64
Commit: 5b20af4

.NET SDKs installed:
6.0.410 [C:\Program Files\dotnet\sdk]
7.0.304 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.18 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.18 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.18 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
Not set

global.json file:
C:\work\ECU300\global.json

Learn more:
https://aka.ms/dotnet/info

Download .NET:
https://aka.ms/dotnet/download

IDE

JetBrains Rider 2023.1.2 Build #RD-231.9011.39, built on May 17, 2023 Runtime version: 17.0.6+10-b829.9 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Windows 10.0 .NET 7.0.2 (Server GC) GC: G1 Young Generation, G1 Old Generation Memory: 1500M Cores: 32 Non-Bundled Plugins: com.layoutmanager (1.4.0) com.4lex4.intellij.solarized (2.4.0) Abc.MoqComplete.Rider (2023.1.0.1) idea.plugin.protoeditor (231.8109.91) com.intellij.resharper.StructuredLogging (2023.1.0.296) com.intellij.resharper.azure (3.50.0.1595-2023.1)

Author: dav1dev
Assignees: -
Labels:

area-System.Threading.Tasks, untriaged

Milestone: -

@stephentoub stephentoub added the needs-author-action An issue or pull request that requires more info or actions from the author. label Jun 26, 2023
@ghost
Copy link

ghost commented Jun 26, 2023

This issue has been marked needs-author-action and may be missing some important information.

@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Jun 26, 2023
@dav1dev
Copy link
Author

dav1dev commented Jun 30, 2023

Thank you for your response. You are absolutely right. It is essential to catch the OperationCancelledException, either on the Delay or on waiting for the task:

try
{
    await Task.Delay(Timeout.Infinite, ctsInfinite.Token);
}
catch (OperationCanceledException)
{
    // ...
}
// or else
try
{
    await t1.WaitAsync(ctsTest.Token);
}
catch (OperationCanceledException)
{
    // ...
}

@dav1dev dav1dev closed this as completed Jun 30, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Jul 30, 2023
@tannergooding tannergooding removed the needs-author-action An issue or pull request that requires more info or actions from the author. label Jun 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants