@@ -15,8 +15,21 @@ Checkpointing allows workflows to save their state at specific points and resume
1515
1616::: zone pivot="programming-language-csharp"
1717
18+ ## Prerequisites
19+
20+ - [ .NET 8.0 SDK or later] ( https://dotnet.microsoft.com/download )
21+ - A new console application
22+
1823## Key Components
1924
25+ ## Install NuGet packages
26+
27+ First, install the required packages for your .NET project:
28+
29+ ``` dotnetcli
30+ dotnet add package Microsoft.Agents.AI.Workflows --prerelease
31+ ```
32+
2033### CheckpointManager
2134
2235The ` CheckpointManager ` provides checkpoint storage and retrieval functionality:
@@ -43,44 +56,48 @@ var workflow = await WorkflowHelper.GetWorkflowAsync();
4356var checkpointManager = CheckpointManager .Default ;
4457
4558// Execute with checkpointing enabled
46- Checkpointed < StreamingRun > checkpointedRun = await InProcessExecution
59+ await using Checkpointed <StreamingRun > checkpointedRun = await InProcessExecution
4760 .StreamAsync (workflow , NumberSignal .Init , checkpointManager );
4861```
4962
5063## State Persistence
5164
5265### Executor State
5366
54- Executors can persist local state that survives checkpoints using the ` ReflectingExecutor ` base class:
67+ Executors can persist local state that survives checkpoints using the ` Executor<T> ` base class:
5568
5669``` csharp
57- internal sealed class GuessNumberExecutor : ReflectingExecutor < GuessNumberExecutor >, IMessageHandler <NumberSignal >
70+ internal sealed class GuessNumberExecutor : Executor <NumberSignal >
5871{
59- private static readonly StateKey StateKey = new ( " GuessNumberExecutor.State" ) ;
72+ private const string StateKey = " GuessNumberExecutor.State" ;
6073
6174 public int LowerBound { get ; private set ; }
6275 public int UpperBound { get ; private set ; }
6376
64- public async ValueTask HandleAsync (NumberSignal message , IWorkflowContext context )
77+ public GuessNumberExecutor () : base (" GuessNumber" )
78+ {
79+ }
80+
81+ public override async ValueTask HandleAsync (NumberSignal message , IWorkflowContext context , CancellationToken cancellationToken = default )
6582 {
6683 int guess = (LowerBound + UpperBound ) / 2 ;
67- await context .SendMessageAsync (guess );
84+ await context .SendMessageAsync (guess , cancellationToken );
6885 }
6986
7087 /// <summary >
7188 /// Checkpoint the current state of the executor.
7289 /// This must be overridden to save any state that is needed to resume the executor.
7390 /// </summary >
7491 protected override ValueTask OnCheckpointingAsync (IWorkflowContext context , CancellationToken cancellationToken = default ) =>
75- context .QueueStateUpdateAsync (StateKey , (LowerBound , UpperBound ));
92+ context .QueueStateUpdateAsync (StateKey , (LowerBound , UpperBound ), cancellationToken );
7693
7794 /// <summary >
7895 /// Restore the state of the executor from a checkpoint.
7996 /// This must be overridden to restore any state that was saved during checkpointing.
8097 /// </summary >
8198 protected override async ValueTask OnCheckpointRestoredAsync (IWorkflowContext context , CancellationToken cancellationToken = default )
8299 {
83- var state = await context .ReadStateAsync <(int , int )>(StateKey );
100+ var state = await context .ReadStateAsync <(int , int )>(StateKey , cancellationToken );
84101 (LowerBound , UpperBound ) = state ;
85102 }
86103}
@@ -158,7 +175,7 @@ Resume execution from a checkpoint and stream events in real-time:
158175// Resume from a specific checkpoint with streaming
159176CheckpointInfo savedCheckpoint = checkpoints [checkpointIndex ];
160177
161- Checkpointed < StreamingRun > resumedRun = await InProcessExecution
178+ await using Checkpointed <StreamingRun > resumedRun = await InProcessExecution
162179 .ResumeStreamAsync (workflow , savedCheckpoint , checkpointManager , runId );
163180
164181await foreach (WorkflowEvent evt in resumedRun .Run .WatchStreamAsync ())
@@ -218,7 +235,7 @@ Create a new workflow instance from a checkpoint:
218235var newWorkflow = await WorkflowHelper .GetWorkflowAsync ();
219236
220237// Resume with the new instance from a saved checkpoint
221- Checkpointed < StreamingRun > newCheckpointedRun = await InProcessExecution
238+ await using Checkpointed <StreamingRun > newCheckpointedRun = await InProcessExecution
222239 .ResumeStreamAsync (newWorkflow , savedCheckpoint , checkpointManager , originalRunId );
223240
224241await foreach (WorkflowEvent evt in newCheckpointedRun .Run .WatchStreamAsync ())
@@ -300,7 +317,7 @@ public static class CheckpointingExample
300317 Console .WriteLine (" Starting workflow with checkpointing..." );
301318
302319 // Execute workflow with checkpointing
303- Checkpointed < StreamingRun > checkpointedRun = await InProcessExecution
320+ await using Checkpointed <StreamingRun > checkpointedRun = await InProcessExecution
304321 .StreamAsync (workflow , NumberSignal .Init , checkpointManager );
305322
306323 // Monitor execution and collect checkpoints
@@ -357,7 +374,7 @@ public static class CheckpointingExample
357374
358375 Console .WriteLine (" Rehydrating from checkpoint 4 with new workflow instance..." );
359376
360- Checkpointed < StreamingRun > newRun = await InProcessExecution
377+ await using Checkpointed < StreamingRun > newRun = await InProcessExecution
361378 .ResumeStreamAsync (newWorkflow , rehydrationCheckpoint , checkpointManager , checkpointedRun .Run .RunId );
362379
363380 await foreach (WorkflowEvent evt in newRun .Run .WatchStreamAsync ())
0 commit comments