Async principalAsync Main
- [x] propuesto[x] Proposed
- [] Prototipo[ ] Prototype
- [] Implementación[ ] Implementation
- [] Especificación[ ] Specification
ResumenSummary
Permita await que se use en el método principal/EntryPoint de una aplicación permitiendo que el punto de entrada devuelva Task / Task<int> y se marque async .Allow await to be used in an application's Main / entrypoint method by allowing the entrypoint to return Task / Task<int> and be marked async.
MotivaciónMotivation
Es muy común al aprender C#, al escribir utilidades basadas en consola y al escribir aplicaciones de prueba pequeñas para que quieran llamar a await async métodos y desde Main.It is very common when learning C#, when writing console-based utilities, and when writing small test apps to want to call and await async methods from Main. Hoy en día, agregamos un nivel de complejidad al forzar que este await se realice en un método asincrónico independiente, lo que hace que los desarrolladores tengan que escribir elementos reutilizables como el siguiente para empezar:Today we add a level of complexity here by forcing such await'ing to be done in a separate async method, which causes developers to need to write boilerplate like the following just to get started:
public static void Main()
{
MainAsync().GetAwaiter().GetResult();
}
private static async Task MainAsync()
{
... // Main body here
}
Podemos eliminar la necesidad de este texto reutilizable y facilitar la introducción, ya que permite que el propio principal sea async tal que se await pueda usar en él.We can remove the need for this boilerplate and make it easier to get started simply by allowing Main itself to be async such that awaits can be used in it.
Diseño detalladoDetailed design
Actualmente se permiten las siguientes firmas entryPoints:The following signatures are currently allowed entrypoints:
static void Main()
static void Main(string[])
static int Main()
static int Main(string[])
Ampliamos la lista de entryPoints permitidos para incluir:We extend the list of allowed entrypoints to include:
static Task Main()
static Task<int> Main()
static Task Main(string[])
static Task<int> Main(string[])
Para evitar riesgos de compatibilidad, estas nuevas firmas solo se considerarán como entryPoints válidas si no hay sobrecargas del conjunto anterior.To avoid compatibility risks, these new signatures will only be considered as valid entrypoints if no overloads of the previous set are present.
El lenguaje/compilador no requerirá que el punto de entrada esté marcado como async , aunque esperamos que la mayoría de los usos se marque como tal.The language / compiler will not require that the entrypoint be marked as async, though we expect the vast majority of uses will be marked as such.
Cuando uno de ellos se identifica como el punto de entrada, el compilador sintetizará un método de punto de entrada real que llama a uno de estos métodos codificados:When one of these is identified as the entrypoint, the compiler will synthesize an actual entrypoint method that calls one of these coded methods:
static Task Main()dará lugar a que el compilador emita el equivalente deprivate static void $GeneratedMain() => Main().GetAwaiter().GetResult();static Task Main()will result in the compiler emitting the equivalent ofprivate static void $GeneratedMain() => Main().GetAwaiter().GetResult();static Task Main(string[])dará lugar a que el compilador emita el equivalente deprivate static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();static Task Main(string[])will result in the compiler emitting the equivalent ofprivate static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();static Task<int> Main()dará lugar a que el compilador emita el equivalente deprivate static int $GeneratedMain() => Main().GetAwaiter().GetResult();static Task<int> Main()will result in the compiler emitting the equivalent ofprivate static int $GeneratedMain() => Main().GetAwaiter().GetResult();static Task<int> Main(string[])dará lugar a que el compilador emita el equivalente deprivate static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();static Task<int> Main(string[])will result in the compiler emitting the equivalent ofprivate static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
Ejemplo de uso:Example usage:
using System;
using System.Net.Http;
class Test
{
static async Task Main(string[] args) =>
Console.WriteLine(await new HttpClient().GetStringAsync(args[0]));
}
InconvenientesDrawbacks
La principal desventaja es simplemente la complejidad adicional de admitir firmas de punto de entrada adicionales.The main drawback is simply the additional complexity of supporting additional entrypoint signatures.
AlternativasAlternatives
Otras variantes consideradas:Other variants considered:
Permite async void .Allowing async void. Necesitamos mantener la semántica igual para que el código la llame directamente, lo que a continuación dificultaría que un punto de entrada generado lo llamara (no se devuelve ninguna tarea).We need to keep the semantics the same for code calling it directly, which would then make it difficult for a generated entrypoint to call it (no Task returned). Podríamos resolver esto generando otros dos métodos, por ejemplo,We could solve this by generating two other methods, e.g.
public static async void Main()
{
... // await code
}
se convierte enbecomes
public static async void Main() => await $MainTask();
private static void $EntrypointMain() => Main().GetAwaiter().GetResult();
private static async Task $MainTask()
{
... // await code
}
También hay preocupaciones en torno a la promoción del uso de async void .There are also concerns around encouraging usage of async void.
Usar "MainAsync" en lugar de "Main" como nombre.Using "MainAsync" instead of "Main" as the name. Aunque se recomienda el sufijo Async para los métodos que devuelven tareas, principalmente sobre la funcionalidad de la biblioteca, que Main no es, y que admiten nombres de punto de entrada adicionales más allá de "Main" no merece la pena.While the async suffix is recommended for Task-returning methods, that's primarily about library functionality, which Main is not, and supporting additional entrypoint names beyond "Main" is not worth it.
Preguntas no resueltasUnresolved questions
N/Dn/a
Design MeetingsDesign meetings
N/Dn/a