diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 70866265e9801..ed23bdf1b29aa 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -910,6 +910,28 @@ updates: dotnet: patterns: - "*" # Prefer a single PR per project update. + - package-ecosystem: "nuget" + directory: "/docs/ai/quickstarts/snippets/mcp-client" #MinimalMCPClient.csproj + schedule: + interval: "weekly" + day: "wednesday" + open-pull-requests-limit: 5 + groups: + # Group .NET updates together for projects. + dotnet: + patterns: + - "*" # Prefer a single PR per project update. + - package-ecosystem: "nuget" + directory: "/docs/ai/quickstarts/snippets/mcp-server" #MinimalMcpServer.csproj + schedule: + interval: "weekly" + day: "wednesday" + open-pull-requests-limit: 5 + groups: + # Group .NET updates together for projects. + dotnet: + patterns: + - "*" # Prefer a single PR per project update. - package-ecosystem: "nuget" directory: "/docs/ai/quickstarts/snippets/prompt-completion/azure-openai" #ExtensionsAzureOpenAI.csproj schedule: @@ -1669,6 +1691,17 @@ updates: dotnet: patterns: - "*" # Prefer a single PR per project update. + - package-ecosystem: "nuget" + directory: "/docs/core/extensions/snippets/hosts/ShortLived.App" #ShortLived.App.csproj + schedule: + interval: "weekly" + day: "wednesday" + open-pull-requests-limit: 5 + groups: + # Group .NET updates together for projects. + dotnet: + patterns: + - "*" # Prefer a single PR per project update. - package-ecosystem: "nuget" directory: "/docs/core/extensions/snippets/http/basic" #basic.csproj schedule: @@ -2164,36 +2197,3 @@ updates: dotnet: patterns: - "*" # Prefer a single PR per project update. - - package-ecosystem: "nuget" - directory: "/docs/core/tutorials/snippets/library-with-visual-studio/csharp/StringLibraryTest" #StringLibraryTest.csproj - schedule: - interval: "weekly" - day: "wednesday" - open-pull-requests-limit: 5 - groups: - # Group .NET updates together for projects. - dotnet: - patterns: - - "*" # Prefer a single PR per project update. - - package-ecosystem: "nuget" - directory: "/docs/core/tutorials/snippets/library-with-visual-studio/csharp/StringLibraryTestNet8" #StringLibraryTest.csproj - schedule: - interval: "weekly" - day: "wednesday" - open-pull-requests-limit: 5 - groups: - # Group .NET updates together for projects. - dotnet: - patterns: - - "*" # Prefer a single PR per project update. - - package-ecosystem: "nuget" - directory: "/docs/core/tutorials/snippets/library-with-visual-studio/vb/StringLibraryTest" #StringLibraryTest.vbproj - schedule: - interval: "weekly" - day: "wednesday" - open-pull-requests-limit: 5 - groups: - # Group .NET updates together for projects. - dotnet: - patterns: - - "*" # Prefer a single PR per project update. diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 064b049b15f1c..5d2ab98478163 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -41,7 +41,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 + uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 with: results_file: results.sarif results_format: sarif diff --git a/docs/ai/get-started-mcp.md b/docs/ai/get-started-mcp.md index ffc03b0b31a44..d0756a0d57904 100644 --- a/docs/ai/get-started-mcp.md +++ b/docs/ai/get-started-mcp.md @@ -95,6 +95,6 @@ Learn more about .NET and MCP using these resources: ## Related content -- [Overview of the .NET + AI ecosystem](/dotnet/ai/dotnet-ai-ecosystem) +- [Overview of the .NET + AI ecosystem](dotnet-ai-ecosystem.md) - [Microsoft.Extensions.AI](/dotnet/ai/ai-extensions) -- [Semantic Kernel overview for .NET](/dotnet/ai/semantic-kernel-dotnet-overview) +- [Semantic Kernel overview for .NET](semantic-kernel-dotnet-overview.md) diff --git a/docs/ai/media/ai-extensions/meai-architecture-diagram.png b/docs/ai/media/ai-extensions/meai-architecture-diagram.png deleted file mode 100644 index a51258c93b699..0000000000000 Binary files a/docs/ai/media/ai-extensions/meai-architecture-diagram.png and /dev/null differ diff --git a/docs/ai/media/llm-eval/eval-app-gen-input.png b/docs/ai/media/llm-eval/eval-app-gen-input.png deleted file mode 100644 index d83c3b8a95f1d..0000000000000 Binary files a/docs/ai/media/llm-eval/eval-app-gen-input.png and /dev/null differ diff --git a/docs/ai/media/llm-eval/eval-app-gen-output.png b/docs/ai/media/llm-eval/eval-app-gen-output.png deleted file mode 100644 index d0b72b5392323..0000000000000 Binary files a/docs/ai/media/llm-eval/eval-app-gen-output.png and /dev/null differ diff --git a/docs/ai/media/llm-eval/eval-app-gen-scenario.png b/docs/ai/media/llm-eval/eval-app-gen-scenario.png deleted file mode 100644 index a2a2aa4711170..0000000000000 Binary files a/docs/ai/media/llm-eval/eval-app-gen-scenario.png and /dev/null differ diff --git a/docs/ai/media/llm-eval/eval-app-test-output.png b/docs/ai/media/llm-eval/eval-app-test-output.png deleted file mode 100644 index 153e47330179c..0000000000000 Binary files a/docs/ai/media/llm-eval/eval-app-test-output.png and /dev/null differ diff --git a/docs/ai/media/llm-eval/eval-app-test-scenario.png b/docs/ai/media/llm-eval/eval-app-test-scenario.png deleted file mode 100644 index f33705fd3c1cc..0000000000000 Binary files a/docs/ai/media/llm-eval/eval-app-test-scenario.png and /dev/null differ diff --git a/docs/ai/media/llm-eval/eval-app.png b/docs/ai/media/llm-eval/eval-app.png deleted file mode 100644 index 11e6d06535fed..0000000000000 Binary files a/docs/ai/media/llm-eval/eval-app.png and /dev/null differ diff --git a/docs/ai/quickstarts/build-mcp-client.md b/docs/ai/quickstarts/build-mcp-client.md index f62de96a19493..ed4bf74b7be66 100644 --- a/docs/ai/quickstarts/build-mcp-client.md +++ b/docs/ai/quickstarts/build-mcp-client.md @@ -61,7 +61,7 @@ Replace the contents of `Program.cs` with the following code: The preceding code accomplishes the following tasks: -- Initializes an `IChatClient` abstraction using the [`Microsoft.Extensions.AI`](/dotnet/ai/microsoft-extensions-ai) libraries. +- Initializes an `IChatClient` abstraction using the [`Microsoft.Extensions.AI`](../microsoft-extensions-ai.md) libraries. - Creates an MCP client and configures it to connect to your MCP server. - Retrieves and displays a list of available tools from the MCP server, which is a standard MCP function. - Implements a conversational loop that processes user prompts and utilizes the tools for responses. diff --git a/docs/ai/quickstarts/snippets/mcp-server/MinimalMcpServer.csproj b/docs/ai/quickstarts/snippets/mcp-server/MinimalMcpServer.csproj index a17b49055f598..c1470993a40a6 100644 --- a/docs/ai/quickstarts/snippets/mcp-server/MinimalMcpServer.csproj +++ b/docs/ai/quickstarts/snippets/mcp-server/MinimalMcpServer.csproj @@ -1,4 +1,4 @@ - + Exe @@ -9,7 +9,7 @@ - + diff --git a/docs/ai/snippets/microsoft-extensions-ai/ConsoleAI.CustomClientMiddle/ConsoleAI.CustomClientMiddle.csproj b/docs/ai/snippets/microsoft-extensions-ai/ConsoleAI.CustomClientMiddle/ConsoleAI.CustomClientMiddle.csproj index 16005c3bde4c2..57a85e1103672 100644 --- a/docs/ai/snippets/microsoft-extensions-ai/ConsoleAI.CustomClientMiddle/ConsoleAI.CustomClientMiddle.csproj +++ b/docs/ai/snippets/microsoft-extensions-ai/ConsoleAI.CustomClientMiddle/ConsoleAI.CustomClientMiddle.csproj @@ -1,4 +1,4 @@ - + Exe @@ -8,7 +8,7 @@ - + diff --git a/docs/ai/snippets/microsoft-extensions-ai/ConsoleAI.ProvideOptions/ConsoleAI.ProvideOptions.csproj b/docs/ai/snippets/microsoft-extensions-ai/ConsoleAI.ProvideOptions/ConsoleAI.ProvideOptions.csproj index 6e0c682243e90..cb6bfe575f31a 100644 --- a/docs/ai/snippets/microsoft-extensions-ai/ConsoleAI.ProvideOptions/ConsoleAI.ProvideOptions.csproj +++ b/docs/ai/snippets/microsoft-extensions-ai/ConsoleAI.ProvideOptions/ConsoleAI.ProvideOptions.csproj @@ -1,4 +1,4 @@ - + Exe @@ -8,7 +8,7 @@ - + diff --git a/docs/ai/snippets/microsoft-extensions-ai/ConsoleAI.ToolCalling/ConsoleAI.ToolCalling.csproj b/docs/ai/snippets/microsoft-extensions-ai/ConsoleAI.ToolCalling/ConsoleAI.ToolCalling.csproj index 6e0c682243e90..cb6bfe575f31a 100644 --- a/docs/ai/snippets/microsoft-extensions-ai/ConsoleAI.ToolCalling/ConsoleAI.ToolCalling.csproj +++ b/docs/ai/snippets/microsoft-extensions-ai/ConsoleAI.ToolCalling/ConsoleAI.ToolCalling.csproj @@ -1,4 +1,4 @@ - + Exe @@ -8,7 +8,7 @@ - + diff --git a/docs/ai/tutorials/snippets/llm-eval/KernelFactoryExamples.cs b/docs/ai/tutorials/snippets/llm-eval/KernelFactoryExamples.cs deleted file mode 100644 index df07aaa984245..0000000000000 --- a/docs/ai/tutorials/snippets/llm-eval/KernelFactoryExamples.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.SemanticKernel; - -// Disable warnings about experimental Semantic Kernel features -#pragma warning disable SKEXP0010 -#pragma warning disable CS8604 - -class KernelFactoryExamples -{ - public static void Examples() - { - CreateKernelEval(); - } - - // - public static Kernel CreateKernelEval() - { - IConfigurationRoot config = new ConfigurationBuilder().AddUserSecrets().Build(); - IKernelBuilder builder = Kernel.CreateBuilder(); - - builder.AddAzureOpenAIChatCompletion( - config["AZURE_OPENAI_MODEL"], - config["AZURE_OPENAI_ENDPOINT"], - config["AZURE_OPENAI_KEY"] - ); - - return builder.Build(); - } - - // - - // - public static Kernel CreateKernelTest() - { - IKernelBuilder builder = Kernel.CreateBuilder(); - - builder.AddOpenAIChatCompletion( - modelId: "phi3", - endpoint: new Uri("http://localhost:11434"), - apiKey: "api" - ); - - return builder.Build(); - } - - // - - // - public static Kernel CreateKernelGenerateData() - { - IConfigurationRoot config = new ConfigurationBuilder().AddUserSecrets().Build(); - IKernelBuilder builder = Kernel.CreateBuilder(); - - builder.AddAzureOpenAIChatCompletion( - config["AZURE_OPENAI_MODEL"], - config["AZURE_OPENAI_ENDPOINT"], - config["AZURE_OPENAI_KEY"] - ); - - return builder.Build(); - } - // -} diff --git a/docs/ai/tutorials/snippets/llm-eval/Program.cs b/docs/ai/tutorials/snippets/llm-eval/Program.cs deleted file mode 100644 index 702f0d365e0d3..0000000000000 --- a/docs/ai/tutorials/snippets/llm-eval/Program.cs +++ /dev/null @@ -1 +0,0 @@ -KernelFactoryExamples.Examples(); \ No newline at end of file diff --git a/docs/ai/tutorials/snippets/llm-eval/llm-eval.csproj b/docs/ai/tutorials/snippets/llm-eval/llm-eval.csproj deleted file mode 100644 index 625ae4e0d758f..0000000000000 --- a/docs/ai/tutorials/snippets/llm-eval/llm-eval.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - Exe - net8.0 - semantic_kernel - enable - enable - ed6763a1-4d17-4e03-aa62-819cfc78ef3b - - - - - - - - - diff --git a/docs/azure/includes/dotnet-all.md b/docs/azure/includes/dotnet-all.md index ada9e3d39864a..165e9b445002a 100644 --- a/docs/azure/includes/dotnet-all.md +++ b/docs/azure/includes/dotnet-all.md @@ -300,7 +300,7 @@ | Resource Management - Mixed Reality | NuGet [1.1.1](https://www.nuget.org/packages/Azure.ResourceManager.MixedReality/1.1.1) | [docs](/dotnet/api/overview/azure/ResourceManager.MixedReality-readme) | GitHub [1.1.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.MixedReality_1.1.1/sdk/mixedreality/Azure.ResourceManager.MixedReality/) | | Resource Management - Mobile Network | NuGet [1.2.0](https://www.nuget.org/packages/Azure.ResourceManager.MobileNetwork/1.2.0) | [docs](/dotnet/api/overview/azure/ResourceManager.MobileNetwork-readme) | GitHub [1.2.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.MobileNetwork_1.2.0/sdk/mobilenetwork/Azure.ResourceManager.MobileNetwork/) | | Resource Management - Mongo Cluster | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.MongoCluster/1.0.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.MongoCluster-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.MongoCluster_1.0.0-beta.1/sdk/mongocluster/Azure.ResourceManager.MongoCluster/) | -| Resource Management - Mongodbatlas | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.MongoDBAtlas/1.0.0-beta.1) | | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.MongoDBAtlas_1.0.0-beta.1/sdk/mongodbatlas/Azure.ResourceManager.MongoDBAtlas/) | +| Resource Management - Mongodbatlas | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.MongoDBAtlas/1.0.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.MongoDBAtlas-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.MongoDBAtlas_1.0.0-beta.1/sdk/mongodbatlas/Azure.ResourceManager.MongoDBAtlas/) | | Resource Management - Monitor | NuGet [1.3.1](https://www.nuget.org/packages/Azure.ResourceManager.Monitor/1.3.1)
NuGet [1.4.0-beta.3](https://www.nuget.org/packages/Azure.ResourceManager.Monitor/1.4.0-beta.3) | [docs](/dotnet/api/overview/azure/ResourceManager.Monitor-readme) | GitHub [1.3.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Monitor_1.3.1/sdk/monitor/Azure.ResourceManager.Monitor/)
GitHub [1.4.0-beta.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Monitor_1.4.0-beta.3/sdk/monitor/Azure.ResourceManager.Monitor/) | | Resource Management - MySQL | NuGet [1.1.1](https://www.nuget.org/packages/Azure.ResourceManager.MySql/1.1.1) | [docs](/dotnet/api/overview/azure/ResourceManager.MySql-readme) | GitHub [1.1.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.MySql_1.1.1/sdk/mysql/Azure.ResourceManager.MySql/) | | Resource Management - Neon Postgres | NuGet [1.0.0](https://www.nuget.org/packages/Azure.ResourceManager.NeonPostgres/1.0.0) | [docs](/dotnet/api/overview/azure/ResourceManager.NeonPostgres-readme) | GitHub [1.0.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.NeonPostgres_1.0.0/sdk/neonpostgres/Azure.ResourceManager.NeonPostgres/) | diff --git a/docs/azure/includes/dotnet-new.md b/docs/azure/includes/dotnet-new.md index 3e186f897c117..4811e6c4bcdf5 100644 --- a/docs/azure/includes/dotnet-new.md +++ b/docs/azure/includes/dotnet-new.md @@ -307,7 +307,7 @@ | Resource Management - Mixed Reality | NuGet [1.1.1](https://www.nuget.org/packages/Azure.ResourceManager.MixedReality/1.1.1) | [docs](/dotnet/api/overview/azure/ResourceManager.MixedReality-readme) | GitHub [1.1.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.MixedReality_1.1.1/sdk/mixedreality/Azure.ResourceManager.MixedReality/) | | Resource Management - Mobile Network | NuGet [1.2.0](https://www.nuget.org/packages/Azure.ResourceManager.MobileNetwork/1.2.0) | [docs](/dotnet/api/overview/azure/ResourceManager.MobileNetwork-readme) | GitHub [1.2.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.MobileNetwork_1.2.0/sdk/mobilenetwork/Azure.ResourceManager.MobileNetwork/) | | Resource Management - Mongo Cluster | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.MongoCluster/1.0.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.MongoCluster-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.MongoCluster_1.0.0-beta.1/sdk/mongocluster/Azure.ResourceManager.MongoCluster/) | -| Resource Management - Mongodbatlas | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.MongoDBAtlas/1.0.0-beta.1) | | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.MongoDBAtlas_1.0.0-beta.1/sdk/mongodbatlas/Azure.ResourceManager.MongoDBAtlas/) | +| Resource Management - Mongodbatlas | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.ResourceManager.MongoDBAtlas/1.0.0-beta.1) | [docs](/dotnet/api/overview/azure/ResourceManager.MongoDBAtlas-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.MongoDBAtlas_1.0.0-beta.1/sdk/mongodbatlas/Azure.ResourceManager.MongoDBAtlas/) | | Resource Management - Monitor | NuGet [1.3.1](https://www.nuget.org/packages/Azure.ResourceManager.Monitor/1.3.1)
NuGet [1.4.0-beta.3](https://www.nuget.org/packages/Azure.ResourceManager.Monitor/1.4.0-beta.3) | [docs](/dotnet/api/overview/azure/ResourceManager.Monitor-readme) | GitHub [1.3.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Monitor_1.3.1/sdk/monitor/Azure.ResourceManager.Monitor/)
GitHub [1.4.0-beta.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.Monitor_1.4.0-beta.3/sdk/monitor/Azure.ResourceManager.Monitor/) | | Resource Management - MySQL | NuGet [1.1.1](https://www.nuget.org/packages/Azure.ResourceManager.MySql/1.1.1) | [docs](/dotnet/api/overview/azure/ResourceManager.MySql-readme) | GitHub [1.1.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.MySql_1.1.1/sdk/mysql/Azure.ResourceManager.MySql/) | | Resource Management - Neon Postgres | NuGet [1.0.0](https://www.nuget.org/packages/Azure.ResourceManager.NeonPostgres/1.0.0) | [docs](/dotnet/api/overview/azure/ResourceManager.NeonPostgres-readme) | GitHub [1.0.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.ResourceManager.NeonPostgres_1.0.0/sdk/neonpostgres/Azure.ResourceManager.NeonPostgres/) | diff --git a/docs/core/extensions/snippets/hosts/ShortLived.App/ShortLived.App.csproj b/docs/core/extensions/snippets/hosts/ShortLived.App/ShortLived.App.csproj index 5d0e643bff550..f71351e3050c1 100644 --- a/docs/core/extensions/snippets/hosts/ShortLived.App/ShortLived.App.csproj +++ b/docs/core/extensions/snippets/hosts/ShortLived.App/ShortLived.App.csproj @@ -8,6 +8,6 @@ - +
diff --git a/docs/core/testing/snippets/order-unit-tests/csharp/NUnit.TestProject/NUnit.Project.csproj b/docs/core/testing/snippets/order-unit-tests/csharp/NUnit.TestProject/NUnit.Project.csproj index 7ebfff4a10cd8..2153a8dde792c 100644 --- a/docs/core/testing/snippets/order-unit-tests/csharp/NUnit.TestProject/NUnit.Project.csproj +++ b/docs/core/testing/snippets/order-unit-tests/csharp/NUnit.TestProject/NUnit.Project.csproj @@ -11,7 +11,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/docs/csharp/index.yml b/docs/csharp/index.yml index 9c985e9031b1f..61a96c6b2d952 100644 --- a/docs/csharp/index.yml +++ b/docs/csharp/index.yml @@ -208,6 +208,34 @@ additionalContent: summary: "You can choose web, mobile, desktop, gaming, IoT, and more." # < 160 chars (optional) items: # Card + - title: Machine learning and AI + links: + - url: ../machine-learning/index.yml + text: Build custom AI solutions with ML.NET + - url: /azure/cognitive-services/ + text: Azure Cognitive Services + - url: /azure/machine-learning + text: Azure Machine Learning + - url: ../fsharp/scenarios/machine-learning.md + text: F# for machine learning + # Card + - title: Cloud + links: + - url: ../azure/index.yml + text: Azure for .NET developers + - url: /dotnet/aspire + text: .NET Aspire + - url: /dotnet/aspire/get-started/quickstart-build-your-first-aspire-app + text: Build cloud-native apps with .NET Aspire + - url: ../azure/migration/app-service.md?preserve-view=true&view=azure-dotnet + text: Migrate on-premises .NET web apps or services + - url: ../azure/key-azure-services.md + text: Azure services for .NET developers + - url: ../azure/sdk/azure-sdk-for-dotnet.md + text: Azure SDK for .NET + - url: ../fsharp/using-fsharp-on-azure/deploying-and-managing.md + text: Deploy Azure resources with F# + # Card - title: Web links: - url: /aspnet/core/tutorials @@ -223,17 +251,6 @@ additionalContent: - url: ../fsharp/scenarios/web-development.md text: F# for web development # Card - - title: Mobile and Desktop - links: - - url: /dotnet/desktop/wpf/ - text: Windows Presentation Foundation - - url: /dotnet/desktop/winforms/ - text: Windows Forms - - url: /dotnet/maui - text: .NET Multi-platform App UI (.NET MAUI) - - url: /azure/developer/mobile-apps - text: Develop mobile apps with Azure - # Card - title: Microservices links: - url: ../architecture/dapr-for-net-developers/index.md @@ -247,31 +264,24 @@ additionalContent: - url: ../core/extensions/cloud-service.md text: Deploy a Worker Service to Azure # Card - - title: Cloud + - title: Mobile, Desktop, and IoT links: - - url: ../azure/index.yml - text: Azure for .NET developers - - url: /dotnet/aspire - text: .NET Aspire - - url: ../azure/migration/app-service.md?preserve-view=true&view=azure-dotnet - text: Migrate on-premises .NET web apps or services - - url: ../azure/key-azure-services.md - text: Azure services for .NET developers - - url: ../azure/sdk/azure-sdk-for-dotnet.md - text: Azure SDK for .NET - - url: ../fsharp/using-fsharp-on-azure/deploying-and-managing.md - text: Deploy Azure resources with F# - # Card - - title: Machine learning and AI - links: - - url: ../machine-learning/index.yml - text: Build custom AI solutions with ML.NET - - url: /azure/cognitive-services/ - text: Azure Cognitive Services - - url: /azure/machine-learning - text: Azure Machine Learning - - url: ../fsharp/scenarios/machine-learning.md - text: F# for machine learning + - url: /dotnet/desktop/wpf/ + text: Windows Presentation Foundation + - url: /dotnet/desktop/winforms/ + text: Windows Forms + - url: /dotnet/maui + text: .NET Multi-platform App UI (.NET MAUI) + - url: /azure/developer/mobile-apps + text: Develop mobile apps with Azure + - url: ../iot/index.yml + text: .NET IoT libraries + - url: ../iot/quickstarts/sensehat.md + text: Get started with IOT in 5 minutes + - url: ../iot/tutorials/blink-led.md + text: Blink an LED + - url: https://aka.ms/dotnet/beginnervideos/youtube/iot + text: .NET IoT 101 video series # Card - title: Game development links: @@ -283,17 +293,6 @@ additionalContent: text: Build games with C# using the MonoGame library - url: https://docs.unity3d.com/Manual/index.html text: Learn how to use Unity to build 2D and 3D games with C# - # Card - - title: Internet of things (IoT) - links: - - url: ../iot/index.yml - text: .NET IoT libraries - - url: ../iot/quickstarts/sensehat.md - text: Get started in 5 minutes - - url: ../iot/tutorials/blink-led.md - text: Blink an LED - - url: https://aka.ms/dotnet/beginnervideos/youtube/iot - text: .NET IoT 101 video series - title: API and language reference # < 60 chars (optional) summary: Search the .NET API and language reference documentation. # < 160 chars (optional) @@ -303,17 +302,21 @@ additionalContent: summary: API reference documentation for .NET url: ../../api/index.md # Card - - title: ".NET Framework API reference" - summary: API reference documentation for .NET Framework - url: ../../api/index.md?view=netframework-4.8&preserve-view=true - # Card - title: "ASP.NET Core API reference" summary: API reference documentation for ASP.NET Core url: ../../api/index.md # Card + - title: ".NET Aspire API reference" + summary: Reference documentation for .NET Aspire + url: ../../api/index.md?view=dotnet-aspire-9.0&preserve-view=true + # Card - title: "ML.NET API reference" summary: API reference documentation for ML.NET url: ../../api/index.md + # Card + - title: ".NET Framework API reference" + summary: API reference documentation for .NET Framework + url: ../../api/index.md?view=netframework-4.8&preserve-view=true # footer (Optional; Remove if not applicable.) footer: "Are you interested in contributing to the .NET docs? For more information, see our [contributor guide](/contribute/dotnet/dotnet-contribute)." diff --git a/docs/csharp/tour-of-csharp/index.yml b/docs/csharp/tour-of-csharp/index.yml index 754d986f5e591..5cf2d9f98229b 100644 --- a/docs/csharp/tour-of-csharp/index.yml +++ b/docs/csharp/tour-of-csharp/index.yml @@ -7,7 +7,7 @@ metadata: title: "C# docs - get started, tutorials, reference." description: "Learn C# programming - for beginning developers, developers new to C#, and experienced C# / .NET developers" ms.topic: landing-page # Required - ms.date: 05/08/2024 + ms.date: 05/29/2025 landingContent: @@ -17,6 +17,8 @@ landingContent: links: - text: Learn C# | Tutorials, courses, videos, and more url: https://dotnet.microsoft.com/learn/csharp + - text: Beginner C# tutorials in your browser + url: ./tutorials/index.md - linkListType: video links: - text: "C# beginner video series" @@ -48,6 +50,8 @@ landingContent: url: ../fundamentals/program-structure/index.md - text: "C# highlights video series" url: https://youtube.com/playlist?list=PLdo4fOcmZ0oU3ZLx6Ul1_HPrr6lFPIn9O + - text: C# Language development strategy + url: ./strategy.md - linkListType: concept links: - text: "Type system" @@ -105,7 +109,7 @@ landingContent: - linkListType: overview links: - text: C# language strategy - url: ../tour-of-csharp/strategy.md + url: ./strategy.md - text: "Programming concepts" url: ../programming-guide/concepts/index.md - linkListType: concept @@ -114,6 +118,14 @@ landingContent: url: ../linq/index.md - text: "Asynchronous programming" url: ../programming-guide/concepts/async/index.md + - linkListType: learn + links: + - text: Learn C# for Java developers + url: ./tips-for-java-developers.md + - text: Learn C# for JavaScript developers + url: ./tips-for-javascript-developers.md + - text: Learn C# for Python developers + url: ./tips-for-python-developers.md - title: "Advanced concepts" linkLists: @@ -130,6 +142,30 @@ landingContent: - text: ".NET Compiler Platform SDK" url: ../roslyn-sdk/index.md + - title: "C# language reference" + linkLists: + - linkListType: reference + links: + - text: "Language reference" + url: ../language-reference/index.yml + - text: "Keywords" + url: ../language-reference/keywords/index.md + - text: "Operators and expressions" + url: ../language-reference/operators/index.md + - text: "Tokens" + url: ../language-reference/tokens/index.md + + - title: "C# language standard" + linkLists: + - linkListType: reference + links: + - text: "Overview" + url: ../specification/overview.md + - text: "C# language specification" + url: ../../../_csharpstandard/standard/README.md + - text: "Feature specifications" + url: ../specification/feature-spec-overview.md + - title: "Stay in touch" linkLists: - linkListType: reference diff --git a/docs/orleans/deployment/snippets/service-fabric/stateless/Orleans.ServiceFabric.Stateless.csproj b/docs/orleans/deployment/snippets/service-fabric/stateless/Orleans.ServiceFabric.Stateless.csproj index c865c0be6e23d..a68d69f090228 100644 --- a/docs/orleans/deployment/snippets/service-fabric/stateless/Orleans.ServiceFabric.Stateless.csproj +++ b/docs/orleans/deployment/snippets/service-fabric/stateless/Orleans.ServiceFabric.Stateless.csproj @@ -13,7 +13,7 @@ - + diff --git a/docs/orleans/grains/cancellation-tokens.md b/docs/orleans/grains/cancellation-tokens.md index 16fefbe58909f..b9c162a564a0d 100644 --- a/docs/orleans/grains/cancellation-tokens.md +++ b/docs/orleans/grains/cancellation-tokens.md @@ -1,60 +1,522 @@ --- -title: Grain cancellation tokens -description: Learn how to use grain cancellation tokens in .NET Orleans. -ms.date: 03/31/2025 -ms.topic: conceptual +title: Use cancellation tokens in Orleans grains +description: Learn how to implement cooperative cancellation in Orleans grain methods. +ms.date: 05/30/2025 --- -# Grain cancellation tokens +# Use cancellation tokens in Orleans grains -The Orleans runtime provides a mechanism called a grain cancellation token, enabling cancellation of an executing grain operation. +Orleans supports cooperative cancellation in grain methods through the standard . This feature lets you stop long-running operations early, cancel work that's no longer needed, and improve your application's responsiveness and resource utilization. -## Description +## Overview - is a wrapper around the standard . It enables cooperative cancellation between threads, thread pool work items, or `Task` objects, and can be passed as a grain method argument. +Orleans supports passing instances to grain interface methods. This works for: + +- Regular grain methods that return `Task`, `Task`, etcetera +- Streaming methods that return `IAsyncEnumerable` +- Both client-to-grain and grain-to-grain calls + +Cancellation is cooperative, meaning your grain implementation must observe the token and respond appropriately for it to be effective. If a cancellation token is not observed, the runtime will not automatically stop a method from executing. This behavior is consistent with the majority of libraries that support . In other words, .NET uses cooperative cancellation. The major benefit of this approach is that cancellation can only occur at clearly identifiable points, not at any given instruction. This lets you run cleanup logic when cancellation is signalled. + +Before a grain call is made, the runtime checks if the provided is already canceled. If so, it immediately throws an without issuing the request. Similarly, if an enqueued request is canceled before a grain begins executing it, it is cancelled without being executed. + +While the grain call is executing, the runtime listens for cancellation, propagating the cancellation signal to the remote caller. Cancellation signals are only propagated while the call is active. Once the call completes (either normally or with an error), any subsequent cancellation signal will not be propagated to the remote caller even if it is still executing. These semantics are similar to how cancellation with remote calls works with other APIs such as `HttpClient`, gRPC, or Azure API clients. + +## Basic usage -A provides a cancellation token through its `Token` property and sends a cancellation message when its method is called. +Follow these steps to add cancellation support to your grain methods: -## Usage +### 1. Define the grain interface -- Instantiate a `CancellationTokenSource` object. This object manages and sends cancellation notifications to individual cancellation tokens. +Add a parameter as the last parameter in your grain interface method. Make it optional with a default value for better usability: ```csharp -var tcs = new GrainCancellationTokenSource(); +public interface IProcessingGrain : IGrainWithGuidKey +{ + Task ProcessDataAsync(string data, int chunks, CancellationToken cancellationToken = default); +} ``` -- Pass the token returned by the property to each grain method listening for cancellation. +### 2. Implement the grain method + +In your grain implementation, regularly check the cancellation token during long-running operations: ```csharp -var waitTask = grain.LongIoWork(tcs.Token, TimeSpan.FromSeconds(10)); +public class ProcessingGrain : Grain, IProcessingGrain +{ + public async Task ProcessDataAsync(string data, int chunks, CancellationToken cancellationToken = default) + { + // Check cancellation before starting work + cancellationToken.ThrowIfCancellationRequested(); + + var results = new List(); + + for (int i = 0; i < chunks; i++) + { + // Check cancellation before each chunk + cancellationToken.ThrowIfCancellationRequested(); + + // Process each chunk + var chunkResult = await ProcessChunkAsync(data, i); + results.Add(chunkResult); + + // Use cancellation token with async operations when possible + await Task.Delay(100, cancellationToken); + } + + return string.Join(", ", results); + } + + private async Task ProcessChunkAsync(string data, int chunkIndex) + { + // Simulate processing work + await Task.Delay(50); + return $"{data}_chunk_{chunkIndex}"; + } +} +``` + +### 3. Call the grain with cancellation + +Create a `CancellationTokenSource` and pass its token to the grain method: + +```csharp +var grain = grainFactory.GetGrain(Guid.NewGuid()); + +using var cts = new CancellationTokenSource(); + +// Set a timeout for automatic cancellation +cts.CancelAfter(TimeSpan.FromSeconds(30)); + +try +{ + var result = await grain.ProcessDataAsync("sample data", 20, cts.Token); + Console.WriteLine($"Result: {result}"); +} +catch (OperationCanceledException) +{ + Console.WriteLine("Operation was canceled"); +} + +// Manual cancellation example +var grain2 = grainFactory.GetGrain(Guid.NewGuid()); +using var cts2 = new CancellationTokenSource(); + +// Start a long-running task +var task = grain2.ProcessDataAsync("large dataset", 1000, cts2.Token); + +// Cancel after 5 seconds +await Task.Delay(5000); +cts2.Cancel(); + +try +{ + await task; +} +catch (OperationCanceledException) +{ + Console.WriteLine("Long processing was canceled"); +} ``` -- A cancellable grain operation needs to handle the underlying `CancellationToken` property of `GrainCancellationToken` just like in any other .NET code. +## Streaming with IAsyncEnumerable<T> + +Cancellation is particularly useful for streaming scenarios where you might want to stop enumeration early. Orleans supports cancellation tokens in async enumerable grain methods. ```csharp -public async Task LongIoWork(GrainCancellationToken tc, TimeSpan delay) +using System.Runtime.CompilerServices; + +public interface IDataStreamGrain : IGrainWithGuidKey +{ + IAsyncEnumerable StreamDataAsync(int count, CancellationToken cancellationToken = default); +} + +public class DataStreamGrain : Grain, IDataStreamGrain { - while (!tc.CancellationToken.IsCancellationRequested) + public async IAsyncEnumerable StreamDataAsync( + int count, + [EnumeratorCancellation] CancellationToken cancellationToken = default) { - await IoOperation(tc.CancellationToken); + for (int i = 0; i < count; i++) + { + // Check cancellation before each yield + cancellationToken.ThrowIfCancellationRequested(); + // Generate or fetch data + var dataPoint = await GenerateDataPointAsync(i, cancellationToken); + yield return dataPoint; + + // Optional: add delay with cancellation support + await Task.Delay(100, cancellationToken); + } + } + + private async Task GenerateDataPointAsync(int index, CancellationToken cancellationToken) + { + // Simulate data generation + await Task.Delay(10, cancellationToken); + return new DataPoint { Index = index, Value = Random.Shared.NextDouble() }; } } + +public record DataPoint(int Index, double Value); ``` -- Call the `GrainCancellationTokenSource.Cancel` method to initiate cancellation. +### Consuming the stream + +When you consume async enumerables, you have two approaches for passing cancellation tokens: [Direct method call with cancellation](#approach-1-direct-method-call-with-cancellation) and [using the WithCancellation extension method](#approach-2-using-the-withcancellation-extension-method). + +#### Approach 1: Direct method call with cancellation + +When the async enumerable method has a `[EnumeratorCancellation]` parameter, pass the token directly: ```csharp -await tcs.Cancel(); +var grain = grainFactory.GetGrain(Guid.NewGuid()); + +using var cts = new CancellationTokenSource(); +cts.CancelAfter(TimeSpan.FromSeconds(10)); // Auto-cancel after 10 seconds + +try +{ + // The token is passed directly to the method and will be combined + // with any token passed to GetAsyncEnumerator() internally + await foreach (var dataPoint in grain.StreamDataAsync(1000, cts.Token)) + { + Console.WriteLine($"Received: {dataPoint}"); + + // Process the data point + // Cancellation will stop the enumeration automatically + } +} +catch (OperationCanceledException) +{ + Console.WriteLine("Streaming was canceled"); +} ``` -- Call the `Dispose` method when finished with the `GrainCancellationTokenSource` object. +#### Approach 2: Using the `WithCancellation` extension method + +For scenarios where you have an existing `IAsyncEnumerable` instance or need to override the cancellation token: ```csharp -tcs.Dispose(); +var grain = grainFactory.GetGrain(Guid.NewGuid()); +var asyncEnumerable = grain.StreamDataAsync(1000); + +using var cts = new CancellationTokenSource(); +cts.CancelAfter(TimeSpan.FromSeconds(10)); + +try +{ + // WithCancellation passes the token to GetAsyncEnumerator() + await foreach (var dataPoint in asyncEnumerable.WithCancellation(cts.Token)) + { + Console.WriteLine($"Received: {dataPoint}"); + } +} +catch (OperationCanceledException) +{ + Console.WriteLine("Streaming was canceled"); +} ``` -#### Important considerations +## Backward compatibility + +One of the key advantages of Orleans's cancellation token support is its backward compatibility. You can modify your grain interfaces and implementations to include or remove parameters without breaking existing clients or other grains that call these methods. + +- **Adding a **: You can add a parameter to an existing grain interface method. If an older client, compiled against the previous interface, calls this method without providing the token, the grain method will receive `CancellationToken.None` from the Orleans runtime. For C# source compatibility with existing grain *implementations* of the interface, it's recommended to define this new parameter as optional in the interface (for example, `CancellationToken cancellationToken = default`). New callers can provide a specific token. + +- **Removing a **: If you remove a parameter from a grain method, callers that were previously passing a token will still have their calls succeed. The Orleans runtime will simply ignore the extra token parameter that the caller is sending, and the grain method will execute without it. The caller might still observe its own token's cancellation and could potentially time out or throw an `OperationCanceledException` on the calling side if its token is canceled, but the grain method itself won't receive the token. + +This flexibility allows you to incrementally adopt cancellation in your Orleans applications without forcing a coordinated update across all components. + +## Configuration + +Configure cancellation behavior through `SiloMessagingOptions` (for silos) and `ClientMessagingOptions` (for clients): + +```csharp +// In your silo configuration +siloBuilder.Configure(options => +{ + // Send cancellation signal when requests timeout (default: true) + options.CancelRequestOnTimeout = true; + + // Wait for callee to acknowledge cancellation (default: false) + // Setting this to true provides stronger cancellation guarantees but may impact performance + options.WaitForCancellationAcknowledgement = false; +}); + +// In your client configuration +clientBuilder.Configure(options => +{ + options.CancelRequestOnTimeout = true; + options.WaitForCancellationAcknowledgement = false; +}); +``` + +### Configuration options explained + +- **`CancelRequestOnTimeout`**: When `true`, Orleans automatically sends a cancellation signal to the target grain if a request times out. This helps notify long-running operations that the caller is no longer waiting. + +- **`WaitForCancellationAcknowledgement`**: When `true`, the cancellation call waits for the target grain to acknowledge that it received the cancellation signal. This provides stronger guarantees but can impact performance in high-throughput scenarios. + +## Diagnostics and troubleshooting + +### Compiler diagnostics + +Orleans code generation enforces that only one parameter is allowed per grain method. If you add more than one, you'll get a build error with diagnostic ID `ORLEANS0109`: + +> The type `YourGrainInterface` contains method `YourMethod` which has multiple CancellationToken parameters. Only a single CancellationToken parameter is supported. + +**Incorrect:** + +```csharp +public interface IMyGrain : IGrainWithGuidKey +{ + // This will cause ORLEANS0109 error + Task ProcessAsync(CancellationToken token1, CancellationToken token2); +} +``` + +**Correct:** + +```csharp +public interface IMyGrain : IGrainWithGuidKey +{ + Task ProcessAsync(CancellationToken cancellationToken = default); +} +``` + +### Monitoring cancellation activity + +Orleans provides metrics to help you monitor cancellation behavior in your application: + +- **`orleans-app-requests-canceled`**: Tracks the number of canceled requests. +- Monitor this metric to understand cancellation patterns and identify potential issues. + +```csharp +// Example: Custom logging for cancellation tracking +public async Task MonitoredOperationAsync(CancellationToken cancellationToken = default) +{ + var stopwatch = Stopwatch.StartNew(); + + try + { + await DoWorkAsync(cancellationToken); + logger.LogInformation("Operation completed in {ElapsedMs}ms", stopwatch.ElapsedMilliseconds); + } + catch (OperationCanceledException) + { + logger.LogInformation("Operation canceled after {ElapsedMs}ms", stopwatch.ElapsedMilliseconds); + throw; + } +} +``` + +## Performance considerations + +### Cancellation batching + +Orleans optimizes performance by batching cancellation requests when many cancellations occur simultaneously. This reduces network overhead and CPU load during high-cancellation scenarios, such as when a service shuts down or when many operations time out simultaneously. + +### Callback execution context + +Callbacks registered on a within a grain execute on the grain's scheduler. This lets you safely perform operations in the context of the grain from cancellation callbacks. + +```csharp +public async Task ExampleWithCancellationCallbackAsync(CancellationToken cancellationToken = default) +{ + // Register a callback that will run on the grain's scheduler + cancellationToken.Register(() => + { + // This runs on the grain's execution context + // Safe to access grain state here + logger.LogInformation("Operation was canceled for grain {GrainId}", this.GetPrimaryKey()); + }); + + // Continue with work... + await DoWorkAsync(cancellationToken); +} +``` + +## Behavioral notes and limitations + +### Cooperative cancellation + +Cancellation in Orleans is cooperative, which means: + +- The grain method must actively check the and respond to cancellation requests. +- Simply passing a canceled token doesn't automatically stop a running operation. +- For best results, check cancellation at regular intervals during long-running work. + +### Timeout integration + +When `CancelRequestOnTimeout` is enabled (default), Orleans automatically sends cancellation signals for timed-out requests: + +```csharp +// If this call times out, Orleans sends a cancellation signal to the grain +await grain.LongRunningOperationAsync(cancellationToken); +``` + +### Cross-silo cancellation + +Cancellation works across silo boundaries in distributed Orleans clusters: + +- Client-to-grain calls can be canceled regardless of which silo hosts the grain. +- Grain-to-grain calls support cancellation even when grains are on different silos. +- Network partitions might delay cancellation signal delivery. + +### Error handling patterns + +Handle cancellation gracefully with proper error handling patterns: + +```csharp +public async Task ProcessWithFallbackAsync( + string data, + CancellationToken cancellationToken = default) +{ + try + { + return await ProcessPrimaryAsync(data, cancellationToken); + } + catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) + { + // Expected cancellation from our token - clean up and re-throw + await CleanupAsync(); + throw; + } + catch (OperationCanceledException) + { + // Cancellation from a different token (unexpected) - treat as error + logger.LogWarning("Received unexpected cancellation"); + throw; + } + catch (Exception ex) + { + // Unexpected error - try fallback if not canceled + if (cancellationToken.IsCancellationRequested) + { + throw new OperationCanceledException(cancellationToken); + } + + logger.LogWarning(ex, "Primary processing failed, trying fallback"); + return await ProcessFallbackAsync(data, cancellationToken); + } +} +``` + +When handling `OperationCanceledException`, always check if the cancellation is from the expected token using the `when` clause. This pattern distinguishes between expected cancellation (from your operation's token) and unexpected cancellation (from other sources). + +### IAsyncEnumerable<T> behavior + +For streaming scenarios with `IAsyncEnumerable`: + +- **Pre-enumeration cancellation**: If the token is canceled before enumeration starts, no items are yielded and an `OperationCanceledException` is thrown immediately. +- **Mid-enumeration cancellation**: If canceled during enumeration, the stream stops at the next cancellation check point (typically the next `yield` or `await` operation). +- **Exception propagation**: An `OperationCanceledException` is thrown to the consumer when cancellation occurs. +- **Resource cleanup**: The async enumerator's `DisposeAsync()` method is called automatically by `await foreach` to clean up resources. +- **Partial results**: Items yielded before cancellation are preserved and delivered to the consumer. + +#### Cancellation timing considerations + +The effectiveness of cancellation depends on how frequently the async iterator checks the cancellation token: + +```csharp +public async IAsyncEnumerable StreamDataAsync( + int count, + [EnumeratorCancellation] CancellationToken cancellationToken = default) +{ + for (int i = 0; i < count; i++) + { + // Good: Check before each item + cancellationToken.ThrowIfCancellationRequested(); + + var data = await ProcessItemAsync(i); + + // Good: Check after long-running operations + cancellationToken.ThrowIfCancellationRequested(); + + yield return data; + + // Good: Use cancellation-aware operations + await Task.Delay(100, cancellationToken); + } +} +``` + +## Legacy: GrainCancellationToken and GrainCancellationTokenSource + +Prior to the direct support for `System.Threading.CancellationToken` in grain methods, Orleans provided a specific mechanism using `GrainCancellationToken` and `GrainCancellationTokenSource`. **This approach is now considered legacy, and `System.Threading.CancellationToken` is the recommended method for implementing cancellation in Orleans grains.** + +The following information is provided for context on older systems or for specific backward compatibility needs. For new development, see the usage described earlier in this article. + +### Overview of GrainCancellationToken + + is a wrapper around the standard . It enables cooperative cancellation between threads, thread pool work items, or `Task` objects, and can be passed as a grain method argument. + +A provides a `GrainCancellationToken` through its `Token` property and sends a cancellation message when its method is called. + +### Using GrainCancellationToken + +To use the legacy `GrainCancellationToken`: + +1. Instantiate a `GrainCancellationTokenSource` object. This object manages and sends cancellation notifications to individual grain cancellation tokens. + + ```csharp + var tcs = new GrainCancellationTokenSource(); + ``` + +1. Pass the token returned by the property to each grain method that should listen for cancellation. + + ```csharp + var waitTask = grain.LongIoWork(tcs.Token, TimeSpan.FromSeconds(10)); + ``` + +1. A cancellable grain operation needs to handle the underlying property of `GrainCancellationToken` just like in any other .NET code. + + ```csharp + public async Task LongIoWork(GrainCancellationToken tc, TimeSpan delay) + { + // Periodically check if cancellation has been requested + while (!tc.CancellationToken.IsCancellationRequested) + { + // Perform a portion of the work + await IoOperation(tc.CancellationToken); + + // Example: tc.CancellationToken.ThrowIfCancellationRequested(); + } + // Perform cleanup if necessary and then exit or throw OperationCanceledException + } + ``` + +1. Call the `GrainCancellationTokenSource.Cancel()` method to initiate cancellation. This signals all `GrainCancellationToken` instances created from this source. + + ```csharp + // Request cancellation + await tcs.Cancel(); + ``` + +1. Call the `GrainCancellationTokenSource.Dispose()` method when finished with the `GrainCancellationTokenSource` object to release its resources. + + ```csharp + tcs.Dispose(); + ``` + +#### Important considerations for GrainCancellationToken + +- The `GrainCancellationTokenSource.Cancel()` method returns a `Task`. To ensure cancellation is robust against transient communication failures, you might need to retry the cancel call. +- Callbacks registered on the underlying `System.Threading.CancellationToken` (accessed via `GrainCancellationToken.CancellationToken`) are subject to single-threaded execution guarantees within the grain activation where they were registered. This means they will run on the grain's task scheduler. +- Each `GrainCancellationToken` can be passed through multiple method invocations if needed. + +## Related topics -- The `GrainCancellationTokenSource.Cancel` method returns a `Task`. To ensure cancellation, retry the cancel call in case of transient communication failure. -- Callbacks registered on the underlying `System.Threading.CancellationToken` are subject to single-threaded execution guarantees within the grain activation where they were registered. -- Each `GrainCancellationToken` can be passed through multiple method invocations. +- +- +- +- +- +- +- [Cancellation in managed threads](/dotnet/standard/threading/cancellation-in-managed-threads) +- [Task cancellation](/dotnet/standard/parallel-programming/task-cancellation) +- [Async streams](/dotnet/csharp/language-reference/proposals/csharp-8.0/async-streams) +- [Orleans timers and reminders](timers-and-reminders.md) +- [Orleans streaming](../streaming/index.md) +- [Orleans GitHub repository]() diff --git a/docs/orleans/toc.yml b/docs/orleans/toc.yml index 50f31026af6b6..bf6d9d4aa97ac 100644 --- a/docs/orleans/toc.yml +++ b/docs/orleans/toc.yml @@ -32,6 +32,8 @@ items: href: grains/timers-and-reminders.md - name: Observers href: grains/observers.md + - name: Cancellation + href: grains/cancellation-tokens.md - name: Request scheduling href: grains/request-scheduling.md - name: Request context @@ -78,8 +80,6 @@ items: href: grains/grainservices.md - name: Stateless worker grains href: grains/stateless-worker-grains.md - - name: Cancellation tokens - href: grains/cancellation-tokens.md - name: Transactions href: grains/transactions.md - name: One-way requests