diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bc8f88781..ae93d03a1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -21,11 +21,6 @@ jobs:
- os: ubuntu-latest
docsTarget: true
cloudTestTarget: true
- # This is here alongside docsTarget because newer docfx doesn't work
- # with .NET 6.
- dotNetVersionOverride: |
- 6.x
- 8.x
- os: ubuntu-arm
runsOn: ubuntu-24.04-arm64-2-core
- os: macos-intel
@@ -54,7 +49,7 @@ jobs:
with:
# Specific .NET version required because GitHub macos ARM image has
# bad pre-installed .NET version
- dotnet-version: ${{ matrix.dotNetVersionOverride || '6.x' }}
+ dotnet-version: '10.x'
- name: Install protoc
uses: arduino/setup-protoc@v3
diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml
index 8e931a8a9..f709bb149 100644
--- a/.github/workflows/package.yml
+++ b/.github/workflows/package.yml
@@ -32,7 +32,7 @@ jobs:
out-file: libtemporal_sdk_core_c_bridge.so
out-prefix: linux-musl-x64
# Need Alpine container since GH runner doesn't have one
- container: mcr.microsoft.com/dotnet/sdk:8.0-alpine
+ container: mcr.microsoft.com/dotnet/sdk:10.0-alpine
protobuf-url: https://github.com/protocolbuffers/protobuf/releases/download/v22.3/protoc-22.3-linux-x86_64.zip
runsOn: ubuntu-latest
- os: macos-intel
@@ -135,6 +135,8 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 10.x
- name: Build package
run: dotnet pack -c Release /p:BridgeLibraryRoot=${{ github.workspace }}/bridge-libraries
@@ -164,7 +166,7 @@ jobs:
- os: ubuntu-arm
runsOn: ubuntu-24.04-arm64-2-core
- os: alpine-latest
- container: mcr.microsoft.com/dotnet/sdk:6.0-alpine
+ container: mcr.microsoft.com/dotnet/sdk:10.0-alpine
runsOn: ubuntu-latest
- os: macos-intel
runsOn: macos-13
@@ -192,11 +194,7 @@ jobs:
with:
# Specific .NET version required because GitHub macos ARM image has
# bad pre-installed .NET version
- dotnet-version: 6.x
-
- - name: Setup .NET (Alpine)
- if: ${{ matrix.os == 'alpine-latest' }}
- run: apk add dotnet6-sdk
+ dotnet-version: 10.x
- name: Run smoke test (non-Windows)
if: ${{ matrix.os != 'windows-latest' && matrix.os != 'windows-arm' }}
diff --git a/README.md b/README.md
index d0a8d3250..e35d8bca2 100644
--- a/README.md
+++ b/README.md
@@ -803,6 +803,9 @@ dotnet_diagnostic.CA1024.severity = none
# Don't force workflows to have static methods
dotnet_diagnostic.CA1822.severity = none
+# Don't force workflows to call async methods
+dotnet_diagnostic.CA1849.severity = none
+
# Do not need ConfigureAwait for workflows
dotnet_diagnostic.CA2007.severity = none
@@ -815,6 +818,9 @@ dotnet_diagnostic.CA5394.severity = none
# Allow async methods to not have await in them
dotnet_diagnostic.CS1998.severity = none
+# Don't force workflows to call async methods
+dotnet_diagnostic.VSTHRD103.severity = none
+
# Don't avoid, but rather encourage things using TaskScheduler.Current in workflows
dotnet_diagnostic.VSTHRD105.severity = none
```
diff --git a/src/Temporalio.Api.Generator/Temporal.Api.Generator.csproj b/src/Temporalio.Api.Generator/Temporal.Api.Generator.csproj
index 1d01086d5..de64433c5 100644
--- a/src/Temporalio.Api.Generator/Temporal.Api.Generator.csproj
+++ b/src/Temporalio.Api.Generator/Temporal.Api.Generator.csproj
@@ -3,7 +3,7 @@
enable
Exe
- net6.0
+ net10.0
diff --git a/tests/Temporalio.SimpleBench/Program.cs b/tests/Temporalio.SimpleBench/Program.cs
index 2bdb96571..8ca5312c8 100644
--- a/tests/Temporalio.SimpleBench/Program.cs
+++ b/tests/Temporalio.SimpleBench/Program.cs
@@ -77,7 +77,7 @@
resultWatch.Stop();
// Cancel worker and wait for cancelled
- cancelSource.Cancel();
+ await cancelSource.CancelAsync();
try
{
await workerTask;
diff --git a/tests/Temporalio.SimpleBench/Temporalio.SimpleBench.csproj b/tests/Temporalio.SimpleBench/Temporalio.SimpleBench.csproj
index 4b69ca335..dbb19137a 100644
--- a/tests/Temporalio.SimpleBench/Temporalio.SimpleBench.csproj
+++ b/tests/Temporalio.SimpleBench/Temporalio.SimpleBench.csproj
@@ -3,14 +3,14 @@
enable
Exe
- net6.0
+ net10.0
-
-
+
+
diff --git a/tests/Temporalio.SmokeTest/Temporalio.SmokeTest.csproj b/tests/Temporalio.SmokeTest/Temporalio.SmokeTest.csproj
index 177da0670..55ca666ec 100644
--- a/tests/Temporalio.SmokeTest/Temporalio.SmokeTest.csproj
+++ b/tests/Temporalio.SmokeTest/Temporalio.SmokeTest.csproj
@@ -3,7 +3,7 @@
enable
Exe
- net6.0
+ net10.0
-
-
-
-
diff --git a/tests/Temporalio.Tests/TestUtils.cs b/tests/Temporalio.Tests/TestUtils.cs
index 84a370617..c48e4a231 100644
--- a/tests/Temporalio.Tests/TestUtils.cs
+++ b/tests/Temporalio.Tests/TestUtils.cs
@@ -19,7 +19,7 @@ public static string ReadAllFileText(
public static int FreePort()
{
- var l = new TcpListener(IPAddress.Loopback, 0);
+ using var l = new TcpListener(IPAddress.Loopback, 0);
l.Start();
int port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
diff --git a/tests/Temporalio.Tests/Testing/ActivityEnvironmentTests.cs b/tests/Temporalio.Tests/Testing/ActivityEnvironmentTests.cs
index 1a18f8ee4..c74fa45ef 100644
--- a/tests/Temporalio.Tests/Testing/ActivityEnvironmentTests.cs
+++ b/tests/Temporalio.Tests/Testing/ActivityEnvironmentTests.cs
@@ -23,7 +23,7 @@ public async Task RunAsync_SimpleActivity_Succeeds()
Info = ActivityEnvironment.DefaultInfo with { ActivityType = "SomeActivity" },
Heartbeater = heartbeats.Add,
};
- env.WorkerShutdownTokenSource.Cancel();
+ await env.WorkerShutdownTokenSource.CancelAsync();
env.Cancel(ActivityCancelReason.Timeout);
var ret = await env.RunAsync(async () =>
{
diff --git a/tests/Temporalio.Tests/Worker/ActivityWorkerTests.cs b/tests/Temporalio.Tests/Worker/ActivityWorkerTests.cs
index fc3e67806..608128c77 100644
--- a/tests/Temporalio.Tests/Worker/ActivityWorkerTests.cs
+++ b/tests/Temporalio.Tests/Worker/ActivityWorkerTests.cs
@@ -433,7 +433,7 @@ await Assert.ThrowsAnyAsync(() => ExecuteActivityAsy
workflowId = handle.Id;
// Wait for activity to be reached, then stop the worker
await activityReached.Task.WaitAsync(TimeSpan.FromSeconds(20));
- workerStoppingSource.Cancel();
+ await workerStoppingSource.CancelAsync();
}));
Assert.True(gotCancellation);
// Check the workflow error
diff --git a/tests/Temporalio.Tests/Worker/NexusWorkerTests.cs b/tests/Temporalio.Tests/Worker/NexusWorkerTests.cs
index 273e3ee14..efd0f71a2 100644
--- a/tests/Temporalio.Tests/Worker/NexusWorkerTests.cs
+++ b/tests/Temporalio.Tests/Worker/NexusWorkerTests.cs
@@ -216,7 +216,12 @@ await AssertMore.HasEventEventuallyAsync(
svc => svc.DoSomething("some-name"),
new() { CancellationToken = cancelSource.Token });
// Cancel and wait for result to bubble out cancel
+#pragma warning disable CA1849 // Call async methods when in an async method
+#pragma warning disable VSTHRD103 // Call async methods when in an async method
+ // https://github.com/temporalio/sdk-dotnet/issues/327
cancelSource.Cancel();
+#pragma warning restore VSTHRD103 // Call async methods when in an async method
+#pragma warning restore CA1849 // Call async methods when in an async method
await handle.GetResultAsync();
}));
var inner = Assert.IsType(wfExc.InnerException);
diff --git a/tests/Temporalio.Tests/Worker/WorkflowWorkerTests.cs b/tests/Temporalio.Tests/Worker/WorkflowWorkerTests.cs
index 2cc46ac72..f52dc53a4 100644
--- a/tests/Temporalio.Tests/Worker/WorkflowWorkerTests.cs
+++ b/tests/Temporalio.Tests/Worker/WorkflowWorkerTests.cs
@@ -284,16 +284,14 @@ public enum Scenario
TaskWaitAsync,
// https://github.com/dotnet/runtime/issues/83159
DataflowReceiveAsync,
- // https://github.com/dotnet/runtime/issues/87481
- TaskWhenAnyWithResultThreeParam,
ListenerDisabledCreateCommand,
// Good
TaskFactoryStartNew,
TaskStart,
TaskContinueWith,
- // https://github.com/dotnet/runtime/issues/87481
TaskWhenAnyWithResultTwoParam,
+ TaskWhenAnyWithResultThreeParam,
WorkflowWhenAnyWithResultThreeParam,
WorkflowWhenAll,
WorkflowRunTask,
@@ -333,9 +331,6 @@ await AssertScenarioFailsTask(
await AssertScenarioFailsTask(
StandardLibraryCallsWorkflow.Scenario.DataflowReceiveAsync,
"not scheduled on workflow scheduler");
- await AssertScenarioFailsTask(
- StandardLibraryCallsWorkflow.Scenario.TaskWhenAnyWithResultThreeParam,
- "not scheduled on workflow scheduler");
await AssertScenarioFailsTask(
StandardLibraryCallsWorkflow.Scenario.ListenerDisabledCreateCommand,
"Function during tracing event listener disabling created workflow commands");
@@ -360,6 +355,8 @@ Task AssertScenarioSucceeds(StandardLibraryCallsWorkflow.Scenario scenario) =>
await AssertScenarioSucceeds(StandardLibraryCallsWorkflow.Scenario.TaskStart);
await AssertScenarioSucceeds(StandardLibraryCallsWorkflow.Scenario.TaskContinueWith);
await AssertScenarioSucceeds(StandardLibraryCallsWorkflow.Scenario.TaskWhenAnyWithResultTwoParam);
+ // Starting in .NET 8, https://github.com/dotnet/runtime/issues/87481 is fixed
+ await AssertScenarioSucceeds(StandardLibraryCallsWorkflow.Scenario.TaskWhenAnyWithResultThreeParam);
await AssertScenarioSucceeds(StandardLibraryCallsWorkflow.Scenario.WorkflowWhenAnyWithResultThreeParam);
await AssertScenarioSucceeds(StandardLibraryCallsWorkflow.Scenario.WorkflowWhenAll);
await AssertScenarioSucceeds(StandardLibraryCallsWorkflow.Scenario.WorkflowRunTask);
@@ -551,7 +548,12 @@ public async Task RunAsync(Input input)
using var cancelSource = new CancellationTokenSource();
if (input.CancelBefore)
{
+#pragma warning disable CA1849 // Call async methods when in an async method
+#pragma warning disable VSTHRD103 // Call async methods when in an async method
+ // https://github.com/temporalio/sdk-dotnet/issues/327
cancelSource.Cancel();
+#pragma warning restore VSTHRD103 // Call async methods when in an async method
+#pragma warning restore CA1849 // Call async methods when in an async method
}
else if (input.CancelAfterMS > 0)
{
@@ -1302,7 +1304,12 @@ public Task RunAsync(int timeoutMs) =>
public async Task ProceedAsync() => shouldProceed = true;
[WorkflowSignal]
+#pragma warning disable CA1849 // Call async methods when in an async method
+#pragma warning disable VSTHRD103 // Call async methods when in an async method
+ // https://github.com/temporalio/sdk-dotnet/issues/327
public async Task CancelWaitAsync() => cancelSource.Cancel();
+#pragma warning restore VSTHRD103 // Call async methods when in an async method
+#pragma warning restore CA1849 // Call async methods when in an async method
}
[Fact]
@@ -2007,7 +2014,12 @@ public async Task RunAsync(Input input)
// Cancel before if desired
if (input.BeforeStart)
{
+#pragma warning disable CA1849 // Call async methods when in an async method
+#pragma warning disable VSTHRD103 // Call async methods when in an async method
+ // https://github.com/temporalio/sdk-dotnet/issues/327
tokenSource.Cancel();
+#pragma warning restore VSTHRD103 // Call async methods when in an async method
+#pragma warning restore CA1849 // Call async methods when in an async method
}
Task activity;
if (input.Local)
@@ -2036,7 +2048,12 @@ public async Task RunAsync(Input input)
if (!input.BeforeStart)
{
await Workflow.DelayAsync(1);
+#pragma warning disable CA1849 // Call async methods when in an async method
+#pragma warning disable VSTHRD103 // Call async methods when in an async method
+ // https://github.com/temporalio/sdk-dotnet/issues/327
tokenSource.Cancel();
+#pragma warning restore VSTHRD103 // Call async methods when in an async method
+#pragma warning restore CA1849 // Call async methods when in an async method
}
await activity;
}
@@ -2255,7 +2272,12 @@ public async Task RunAsync(bool beforeStart)
// Cancel before if desired
if (beforeStart)
{
+#pragma warning disable CA1849 // Call async methods when in an async method
+#pragma warning disable VSTHRD103 // Call async methods when in an async method
+ // https://github.com/temporalio/sdk-dotnet/issues/327
tokenSource.Cancel();
+#pragma warning restore VSTHRD103 // Call async methods when in an async method
+#pragma warning restore CA1849 // Call async methods when in an async method
}
var handle = await Workflow.StartChildWorkflowAsync(
(ChildWorkflow wf) => wf.RunAsync(),
@@ -2263,7 +2285,12 @@ public async Task RunAsync(bool beforeStart)
// If not cancel before, cancel now
if (!beforeStart)
{
+#pragma warning disable CA1849 // Call async methods when in an async method
+#pragma warning disable VSTHRD103 // Call async methods when in an async method
+ // https://github.com/temporalio/sdk-dotnet/issues/327
tokenSource.Cancel();
+#pragma warning restore VSTHRD103 // Call async methods when in an async method
+#pragma warning restore CA1849 // Call async methods when in an async methodßß
}
await handle.GetResultAsync();
}
@@ -4088,7 +4115,7 @@ await ExecuteWorkerAsync(async worker =>
await AssertMore.EqualEventuallyAsync(true, () => handle.QueryAsync(wf => wf.Waiting));
// Cancel and confirm error
- updateCancelSource.Cancel();
+ await updateCancelSource.CancelAsync();
await Assert.ThrowsAsync(() => updateTask);
});
}
@@ -5297,7 +5324,12 @@ await Workflow.ExecuteActivityAsync(
}
[WorkflowSignal]
+#pragma warning disable CA1849 // Call async methods when in an async method
+#pragma warning disable VSTHRD103 // Call async methods when in an async method
+ // https://github.com/temporalio/sdk-dotnet/issues/327
public async Task CancelUpdateAsync(int number) => cancellations[number].Cancel();
+#pragma warning restore VSTHRD103
+#pragma warning restore CA1849
#pragma warning disable VSTHRD110 // Returning tasks is ok
private Task WaitAsync(CancellationToken? cancellationToken = null) =>
@@ -6512,7 +6544,7 @@ await AssertMore.EventuallyAsync(async () =>
});
// Now cancel token and confirm update cancellation results in proper cancellation
- cancelSource.Cancel();
+ await cancelSource.CancelAsync();
await Assert.ThrowsAsync(
() => updateTask);
// Note, currently in this use case the handle isn't set either, the same exception