Skip to content

[API Proposal]: Provide an async entry point helper to enable platforms that need an async return from Main() #121046

@AaronRobinsonMSFT

Description

@AaronRobinsonMSFT

Background and motivation

All .NET main entrypoints are expected to be synchronous. In C# 7.1, the ability to mark Main as async was introduced, but the actual entry point of the .NET assembly remained synchronous. For browser scenarios, the entrypoint must be asynchronous so that the JavaScript message loop can continue to run and handle various requests for browser provided services (for example, I/O).

The proposed API would allow for Roslyn to emit a consistent API call for all scenarios. The runtime implementation would be different based on target and allow for the desired behavior when running in a browser environment.

See #120976 (comment) for additional context.

API Proposal

namespace System.Runtime.CompilerServices;

[EditorBrowsable(EditorBrowsableState.Never)]
public static partial class AsyncHelpers
{
+    public static void ExecuteAsyncEntryPoint(Task main);
+    public static int ExecuteAsyncEntryPoint(Task<int> main);
}

API Usage

Roslyn would generate the following code for async Main.

Main returns void

static async void Main() { }

// Roslyn generated
static void <Main>(string[] args) => AsyncHelpers.ExecuteAsyncEntryPoint(Main(args));

Main returns int

static async int Main() { return 0; }

// Roslyn generated
static int <Main>(string[] args) => AsyncHelpers.ExecuteAsyncEntryPoint(Main(args));

Alternative Designs

An alternative to this is to embed in the runtime how to determine from the official synchronous entry point the actual user defined asynchronous entrypoint. Given the current generated code by Roslyn the runtime would discover the entrypoint, that is <Main>, if the user defined entrypoint was called Main, extract the name between the <> and look up that name in class.

It is desired to avoid embedding this logic in the runtime, which would limit Roslyn from changing how name mangling of an async main entry point is done.

Risks

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions