Skip to content

Commit 4c59ac8

Browse files
authored
add TaskCompletionSource SetCanceled with CancellationToken (#202)
1 parent 847359f commit 4c59ac8

File tree

6 files changed

+84
-2
lines changed

6 files changed

+84
-2
lines changed

apiCount.include.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
**API count: 326**
1+
**API count: 327**

api_list.include.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,11 @@
330330
* `Task<TResult> WaitAsync<TResult>(TimeSpan, CancellationToken)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task-1.waitasync#system-threading-tasks-task-1-waitasync(system-timespan-system-threading-cancellationtoken))
331331

332332

333+
#### TaskCompletionSource<T>
334+
335+
* `void SetCanceled<T>(CancellationToken)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcompletionsource-1.setcanceled#system-threading-tasks-taskcompletionsource-1-setcanceled(system-threading-cancellationtoken))
336+
337+
333338
#### TextReader
334339

335340
* `ValueTask<Int32> ReadAsync(Memory<Char>, CancellationToken)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.io.textreader.readasync#system-io-textreader-readasync(system-memory((system-char))-system-threading-cancellationtoken))

readme.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ The package targets `netstandard2.0` and is designed to support the following ru
1212
* `net5.0`, `net6.0`, `net7.0`, `net8.0`, `net9.0`
1313

1414

15-
**API count: 326**<!-- singleLineInclude: apiCount. path: /apiCount.include.md -->
15+
**API count: 327**<!-- singleLineInclude: apiCount. path: /apiCount.include.md -->
1616

1717

1818
**See [Milestones](../../milestones?state=closed) for release notes.**
@@ -739,6 +739,11 @@ The class `Polyfill` includes the following extension methods:
739739
* `Task<TResult> WaitAsync<TResult>(TimeSpan, CancellationToken)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task-1.waitasync#system-threading-tasks-task-1-waitasync(system-timespan-system-threading-cancellationtoken))
740740

741741

742+
#### TaskCompletionSource<T>
743+
744+
* `void SetCanceled<T>(CancellationToken)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcompletionsource-1.setcanceled#system-threading-tasks-taskcompletionsource-1-setcanceled(system-threading-cancellationtoken))
745+
746+
742747
#### TextReader
743748

744749
* `ValueTask<Int32> ReadAsync(Memory<Char>, CancellationToken)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.io.textreader.readasync#system-io-textreader-readasync(system-memory((system-char))-system-threading-cancellationtoken))

src/Consume/Consume.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,13 @@ void CancellationTokenUnsafeRegister()
276276
}, null);
277277
}
278278

279+
void TaskCompletionSource_SetCanceled_WithCancellationToken()
280+
{
281+
var completionSource = new TaskCompletionSource<int>();
282+
var tokenSource = new CancellationTokenSource();
283+
completionSource.SetCanceled(tokenSource.Token);
284+
}
285+
279286
async Task ProcessWaitForExitAsync()
280287
{
281288
var process = new Process();
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// <auto-generated />
2+
#pragma warning disable
3+
4+
#if !NET5_0_OR_GREATER
5+
6+
using System;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
using Link = System.ComponentModel.DescriptionAttribute;
10+
11+
static partial class Polyfill
12+
{
13+
/// <summary>
14+
/// Transitions the underlying <see cref="Task{TResult}"/> into the <see cref="TaskStatus.Canceled"/> state
15+
/// using the specified token.
16+
/// </summary>
17+
/// <param name="cancellationToken">The cancellation token with which to cancel the <see cref="Task{TResult}"/>.</param>
18+
/// <exception cref="InvalidOperationException">
19+
/// The underlying <see cref="Task{TResult}"/> is already in one of the three final states:
20+
/// <see cref="TaskStatus.RanToCompletion"/>,
21+
/// <see cref="TaskStatus.Faulted"/>, or
22+
/// <see cref="TaskStatus.Canceled"/>.
23+
/// </exception>
24+
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcompletionsource-1.setcanceled#system-threading-tasks-taskcompletionsource-1-setcanceled(system-threading-cancellationtoken)")]
25+
public static void SetCanceled<T>(
26+
this TaskCompletionSource<T> target,
27+
CancellationToken cancellationToken)
28+
{
29+
if (target.TrySetCanceled(cancellationToken))
30+
{
31+
return;
32+
}
33+
34+
throw new InvalidOperationException("An attempt was made to transition a task to a final state when it had already completed.");
35+
}
36+
}
37+
#endif
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#pragma warning disable CS4014
2+
partial class PolyfillTests
3+
{
4+
[Test]
5+
public async Task TaskCompletionSource_SetCanceled_WithCancellationToken()
6+
{
7+
var completionSource = new TaskCompletionSource<int>();
8+
var tokenSource = new CancellationTokenSource();
9+
10+
// Simulate some background work that will cancel the task
11+
Task.Run(async () =>
12+
{
13+
await Task.Delay(20); // Simulate a delay
14+
completionSource.SetCanceled(tokenSource.Token);
15+
});
16+
17+
try
18+
{
19+
// Await the task
20+
var result = await completionSource.Task;
21+
Console.WriteLine($"Task completed with result: {result}");
22+
}
23+
catch (TaskCanceledException)
24+
{
25+
Console.WriteLine("Task was canceled.");
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)