* Add .NET reference files for temporal-developer skill Created 11 .NET reference files covering: dotnet.md (overview/quick start), patterns.md, determinism.md, determinism-protection.md, error-handling.md, testing.md, versioning.md, observability.md, data-handling.md, gotchas.md, and advanced-features.md. Follows Python/TypeScript patterns with .NET-specific content for Task determinism, CancellationToken, dependency injection, etc. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix .NET alignment issues from self-review - dotnet.md: Reduce Determinism Rules section to brief cross-reference (was duplicating determinism.md content) - patterns.md: Add ParentClosePolicy to Child Workflows example - gotchas.md: Add missing "Heartbeat Timeout Too Short" subsection - versioning.md: Add missing Key Concepts, Deployment Strategies, Query Filters, PINNED/AUTO_UPGRADE guidance, CLI examples - advanced-features.md: Add worker-level heading for exception types Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix .NET correctness issues from verification pass - patterns.md: Fix cancellation pattern to use official TemporalException.IsCanceledException(e) with detached CancellationTokenSource - advanced-features.md: Fix DI hosting example to use official AddHostedTemporalWorker(clientTargetHost:, clientNamespace:, taskQueue:) pattern Verified against official SDK README, API docs, and temporal-docs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Update supported language references to include .NET - SKILL.md: Add "Temporal .NET" and "Temporal C#" trigger phrases, update overview to mention .NET, add .NET entry in getting started - core/determinism.md: Add .NET entry in SDK Protection Mechanisms Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Edits to advanced features * edits to determinism protection, and move the .editorconfig section * missed one * edit determinism.md * edit error-handling.md * edit gotchas.md * edit patterns.md * edit versioning.md * edit observability.md * fix metrics * self-review round 1 * minor correctness fixed * Update references/dotnet/patterns.md Co-authored-by: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com> * address comments, clarify reference to earlier code snippet * clarify that operations are forbidden IN WORKFLOWS * cleanup workflow cancellation handling example * add task token retrieval comment * update .net requirements * Fix propagation of workflow cancellation --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Justin Anderson <44687433+jmaeagle99@users.noreply.github.com>
2.6 KiB
.NET SDK Determinism
Overview
The .NET SDK has NO runtime sandbox (unlike Python/TypeScript). Workflows must be deterministic for replay, and determinism is enforced by developer convention and runtime task detection via an EventListener (see references/dotnet/determinism-protection.md).
Why Determinism Matters: History Replay
Temporal provides durable execution through History Replay. When a Worker restores workflow state, it re-executes workflow code from the beginning. This requires the code to be deterministic. See references/core/determinism.md for a deep explanation.
Forbidden Operations in Workflows
The following are forbidden inside workflow code but are appropriate to use in activities.
// DO NOT do these in workflows:
await Task.Run(() => { }); // Uses default scheduler
await Task.Delay(TimeSpan.FromSeconds(1)); // System timer
var now = DateTime.UtcNow; // System clock
var r = new Random().Next(); // Non-deterministic
var id = Guid.NewGuid(); // Non-deterministic
File.ReadAllText("file.txt"); // I/O
await httpClient.GetAsync("..."); // Network I/O
Most non-determinism and side effects should be wrapped in Activities.
Safe Builtin Alternatives
| Forbidden | Safe Alternative |
|---|---|
DateTime.Now / DateTime.UtcNow |
Workflow.UtcNow |
Random |
Workflow.Random |
Guid.NewGuid() |
Workflow.NewGuid() |
Task.Delay |
Workflow.DelayAsync |
Thread.Sleep |
Workflow.DelayAsync |
Task.Run |
Workflow.RunTaskAsync |
Task.WhenAll |
Workflow.WhenAllAsync |
Task.WhenAny |
Workflow.WhenAnyAsync |
System.Threading.Mutex |
Temporalio.Workflows.Mutex |
System.Threading.Semaphore |
Temporalio.Workflows.Semaphore |
CancellationTokenSource.CancelAsync |
CancellationTokenSource.Cancel |
Testing Replay Compatibility
Use WorkflowReplayer to verify your code changes are compatible with existing histories. See the Workflow Replay Testing section of references/dotnet/testing.md.
Best Practices
- Always use
Workflow.*APIs instead of standard .NET equivalents (see table above) - Never use
ConfigureAwait(false)in workflows - Use
SortedDictionaryor sort before iterating collections - Move all I/O operations (network, filesystem, database) into activities
- Use
Workflow.Loggerinstead ofConsole.WriteLinefor replay-safe logging - Keep workflow code focused on orchestration; delegate non-deterministic work to activities
- Test with replay after making changes to workflow definitions