Skip to content

Provide a built-in way to create APM methods from a Task-based method #61729

@GSPP

Description

@GSPP

EDITED by @stephentoub on 1/26/2023:

We don't want to reinvigorate the legacy pattern, so we can bury these helpers now as statics on the IAsyncResult interface itself... the only reason to reach for that interface is if you're using that legacy pattern, and these methods naturally fit there:

namespace System
{
    public interface IAsyncResult
    {
+        public static IAsyncResult BeginFromTask(Task task, AsyncCallback? callback, object? state);
+        public static void EndFromTask(IAsyncResult asyncResult);
+        public static TResult EndFromTask<TResult>(IAsyncResult asyncResult);
+        public static Task UnwrapTask(IAsyncResult asyncResult);
+        public static Task<TResult> UnwrapTask<TResult>(IAsyncResult asyncResult);
    }
}

Alternatively, we can introduce a new class:

namespace System.Threading.Tasks
{
+    public static class TaskToAsyncResult
+    {
+        public static IAsyncResult Begin(Task task, AsyncCallback? callback, object? state);
+        public static void End(IAsyncResult asyncResult);
+        public static TResult End<TResult>(IAsyncResult asyncResult);
+        public static Task Unwrap(IAsyncResult asyncResult);
+        public static Task<TResult> Unwrap<TResult>(IAsyncResult asyncResult);
+    }
}

Stream provides both APM and Task methods for reading and writing. When creating a custom stream, you ideally override them both and provide a functional implementation. It is desirable to be able to implement this based on Task and possibly await just once and reuse that code for the APM methods.

The Framework does it that way in multiple places using the TaskToApm class (https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/Threading/Tasks/TaskToApm.cs).

I suggest that the Framework should have a built-in way to do this. Possibly, the existing TaskToApm class can just be polished and made public.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions