Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions docs/standard/threading/cancellation-in-managed-threads.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
title: "Cancellation in Managed Threads"
description: Understand cancellation in managed threads. Learn about cancellation tokens in cooperative cancellation of asynchronous or long-running synchronous operations.
ms.date: "03/30/2017"
ms.date: "03/17/2026"
ai-usage: ai-assisted
dev_langs:
- "csharp"
- "vb"
Expand Down Expand Up @@ -129,14 +130,21 @@ The general pattern for implementing the cooperative cancellation model is:

For a more complete example, see [How to: Listen for Cancellation Requests That Have Wait Handles](how-to-listen-for-cancellation-requests-that-have-wait-handles.md).

### Listening to Multiple Tokens Simultaneously
### Listen to multiple tokens simultaneously

In some cases, a listener may have to listen to multiple cancellation tokens simultaneously. For example, a cancelable operation may have to monitor an internal cancellation token in addition to a token passed in externally as an argument to a method parameter. To accomplish this, create a linked token source that can join two or more tokens into one token, as shown in the following example.
In some cases, a listener might have to listen to multiple cancellation tokens simultaneously. For example, a cancelable operation might have to monitor an internal cancellation token in addition to a token passed in externally as an argument to a method parameter. To accomplish this, create a linked token source that can join two or more tokens into one token.

The following example shows the most common use of a linked token: a child token that is cancelled when the parent token is cancelled. You can also cancel the child independently by calling `Cancel` on the child `CancellationTokenSource`.

:::code language="csharp" source="./snippets/cancellation-in-managed-threads/csharp/LinkedTokens/Program.cs" id="LinkedTokens":::
:::code language="vb" source="./snippets/cancellation-in-managed-threads/vb/LinkedTokens/Program.vb" id="LinkedTokens":::

A more complex scenario involves a cancelable operation that must monitor both an external token passed in from a caller and an internal token. The following example shows how to create such a linked token.

[!code-csharp[Cancellation#7](../../../samples/snippets/csharp/VS_Snippets_Misc/cancellation/cs/cancellationex13.cs#7)]
[!code-vb[Cancellation#7](../../../samples/snippets/visualbasic/VS_Snippets_Misc/cancellation/vb/cancellationex13.vb#7)]

Notice that you must call `Dispose` on the linked token source when you are done with it. For a more complete example, see [How to: Listen for Multiple Cancellation Requests](how-to-listen-for-multiple-cancellation-requests.md).
Notice that you must call `Dispose` on the linked token source when you're done with it. For a more complete example, see [How to: Listen for Multiple Cancellation Requests](how-to-listen-for-multiple-cancellation-requests.md).

## Cooperation Between Library Code and User Code

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// <LinkedTokens>
using System.Threading;

// Create the parent CancellationTokenSource.
using var parentCts = new CancellationTokenSource();
CancellationToken parentToken = parentCts.Token;

// Create a linked child CancellationTokenSource.
// The child token is cancelled when the parent token is cancelled.
using var childCts = CancellationTokenSource.CreateLinkedTokenSource(parentToken);
CancellationToken childToken = childCts.Token;

Console.WriteLine($"Parent is cancelled: {parentToken.IsCancellationRequested}");
Console.WriteLine($"Child is cancelled: {childToken.IsCancellationRequested}");

// Cancel the parent.
parentCts.Cancel();

Console.WriteLine($"Parent is cancelled: {parentToken.IsCancellationRequested}");
Console.WriteLine($"Child is cancelled: {childToken.IsCancellationRequested}");

// Output:
// Parent is cancelled: False
// Child is cancelled: False
// Parent is cancelled: True
// Child is cancelled: True
// </LinkedTokens>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<RootNamespace>LinkedTokens</RootNamespace>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
' <LinkedTokens>
Imports System.Threading

Module Program
Sub Main()
' Create the parent CancellationTokenSource.
Using parentCts As New CancellationTokenSource()
Dim parentToken As CancellationToken = parentCts.Token

' Create a linked child CancellationTokenSource.
' The child token is cancelled when the parent token is cancelled.
Using childCts As CancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(parentToken)
Dim childToken As CancellationToken = childCts.Token

Console.WriteLine($"Parent is cancelled: {parentToken.IsCancellationRequested}")
Console.WriteLine($"Child is cancelled: {childToken.IsCancellationRequested}")

' Cancel the parent.
parentCts.Cancel()

Console.WriteLine($"Parent is cancelled: {parentToken.IsCancellationRequested}")
Console.WriteLine($"Child is cancelled: {childToken.IsCancellationRequested}")
End Using
End Using
End Sub
End Module
' Output:
' Parent is cancelled: False
' Child is cancelled: False
' Parent is cancelled: True
' Child is cancelled: True
' </LinkedTokens>
Loading