From 6fbee7b0ae08eb3d01d3d739ea6e61deed57c225 Mon Sep 17 00:00:00 2001 From: ahmad-codex Date: Wed, 28 Oct 2026 21:17:07 +0200 Subject: [PATCH 1/2] fix: ignore Task result for activities declared as Task (#975) --- src/Temporalio/Activities/ActivityDefinition.cs | 5 +++-- .../Activities/ActivityDefinitionTests.cs | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Temporalio/Activities/ActivityDefinition.cs b/src/Temporalio/Activities/ActivityDefinition.cs index d8e12d16..5defaae4 100644 --- a/src/Temporalio/Activities/ActivityDefinition.cs +++ b/src/Temporalio/Activities/ActivityDefinition.cs @@ -212,9 +212,10 @@ public static IReadOnlyCollection CreateAll(Type type, objec if (result is Task resultTask) { await resultTask.ConfigureAwait(false); - // We have to use reflection to extract value if it's a Task<> + // We have to use reflection to extract value if it's a Task<>, but not if the + // activity is declared as a non-generic Task var resultTaskType = resultTask.GetType(); - if (resultTaskType.IsGenericType) + if (ReturnType != typeof(Task) && resultTaskType.IsGenericType) { result = resultTaskType.GetProperty("Result")!.GetValue(resultTask); } diff --git a/tests/Temporalio.Tests/Activities/ActivityDefinitionTests.cs b/tests/Temporalio.Tests/Activities/ActivityDefinitionTests.cs index 253a951c..790c1b73 100644 --- a/tests/Temporalio.Tests/Activities/ActivityDefinitionTests.cs +++ b/tests/Temporalio.Tests/Activities/ActivityDefinitionTests.cs @@ -123,6 +123,15 @@ public async Task InvokeAsync_AsyncDelegate_CanInvoke() await ActivityDefinition.Create(act).InvokeAsync(new object?[] { 123 })); } + [Fact] + public async Task InvokeAsync_TaskDelegateReturningGenericTask_HasNoResult() + { + var act = [Activity("MyActivity")] Task (int param) => Task.FromResult(param + 5); + Assert.Equal( + ValueTuple.Create(), + await ActivityDefinition.Create(act).InvokeAsync(new object?[] { 123 })); + } + [Fact] public async Task InvokeAsync_ManualInvoker_IsCalled() { From 25c07f4e44485dced0e71f9064ac4276ae5becd0 Mon Sep 17 00:00:00 2001 From: ahmad-codex Date: Wed, 28 Oct 2026 21:17:51 +0200 Subject: [PATCH 2/2] docs: describe ReturnType use for non-generic Task --- src/Temporalio/Activities/ActivityDefinition.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Temporalio/Activities/ActivityDefinition.cs b/src/Temporalio/Activities/ActivityDefinition.cs index 5defaae4..a5d42c2f 100644 --- a/src/Temporalio/Activities/ActivityDefinition.cs +++ b/src/Temporalio/Activities/ActivityDefinition.cs @@ -37,8 +37,8 @@ private ActivityDefinition( public string? Name { get; private init; } /// - /// Gets the return type for the definition. This may be a Task for async activities. This - /// is currently unused (callers are expected to provide the return type as needed). + /// Gets the return type for the definition. This may be a Task for async activities. When + /// it is a non-generic Task, the activity completes with no result. /// public Type ReturnType { get; private init; } @@ -84,7 +84,7 @@ public static ActivityDefinition Create(Delegate del) /// Create an activity definition manually from the given values. /// /// Name to use for the activity or null for dynamic. - /// Return type of the activity. This is currently unused. + /// Return type of the activity. A non-generic Task means no result. /// Parameter types for the invoker. /// Minimum number of parameters that must be provided /// to the invoker.