síncrono sincronico sincronica sincrona qué funciones español diacronico await asíncrono async asincronico aprendizaje c# reflection asynchronous

sincronico - ¿Cómo puedo saber si un método de C#es asincrónico/espera a través de la reflexión?



sincronico y asincronico (3)

p.ej

class Foo { public async Task Bar() { await Task.Delay(500); } }

Si estamos reflexionando sobre esta clase y método, ¿cómo puedo determinar si este es un método real async / await en lugar de simplemente un método que devuelve una tarea?

class Foo { public Task Bar() { return Task.Delay(500); } }


Aquí hay un ejemplo de dos métodos, y le pregunto por qué cree que deberían tratarse de manera diferente:

public static async Task<int> M1(int value) { await Task.Delay(20000); return value; } public static Task<int> M2(int value) { return Task.Delay(20000).ContinueWith<int>(_=>value); }

Ambos tienen, dentro de una onda manual, el mismo comportamiento de tiempo de ejecución: durante 20 segundos no hacen nada (y no se aferran a un hilo durante ese período) y luego ejecutan un pequeño delegado que simplemente devuelve el valor que inicialmente era pasado al método.

Y, sin embargo, vas a tratar a uno de forma muy diferente a la otra porque elijo usar el compilador para ocultar algunas de las tuberías.


Damien_The_Unbeliever lanzó un desafío interesante. Creo que buscar AsyncStateMachineAttribute no es una solución suficiente. La pregunta original no debería ser si el método es asíncrono. En cambio, debería ser si es aguardable. Ambas muestras de métodos en la respuesta de Damián serán verdaderas si comprueba el método GetAwaiter() en el tipo de devolución. Sin embargo, solo el método marcado como AsyncStateMachineAttribute incluirá AsyncStateMachineAttribute en la colección de atributos personalizados.

Saber si el método es aguardable es importante si desea utilizar MethodInfo.Invoke() para llamar al método y no sabe de antemano si los métodos, que podrían registrarse en un intermediario de mensajes, por ejemplo, son a la espera.

var isAwaitable = _methodInfo.ReturnType.GetMethod("GetAwaiter") != null; object result = null; if (isAwaitable) { result = await (dynamic)_methodInfo.Invoke(_instance, _parameterArray); } else { result = _methodInfo.Invoke(_instance, _parameterArray); }


En mi copia de su código, MethodInfo para el método async contiene los siguientes elementos en la propiedad CustomAttributes :

  • un DebuggerStepThroughAttribute
  • un AsyncStateMachineAttribute

mientras que MethodInfo para el método normal no contiene elementos en su propiedad CustomAttributes .

Parece que el AsyncStateMachineAttribute debe encontrarse de manera confiable en un método async y no en uno estándar .

Editar: ¡De hecho, esa página incluso tiene lo siguiente en los ejemplos!

Como muestra el siguiente ejemplo, puede determinar si un método está marcado con el modificador Async (Visual Basic) o asincrónico (Referencia C #). En el ejemplo, IsAsyncMethod realiza los siguientes pasos:

  • Obtiene un objeto MethodInfo para el nombre del método mediante Type.GetMethod.

  • Obtiene un objeto Type para el atributo utilizando GetType Operator (Visual Basic) o typeof (C # Reference).

  • Obtiene un objeto de atributo para el método y el tipo de atributo utilizando MethodInfo.GetCustomAttribute. Si GetCustomAttribute devuelve Nothing (Visual Basic) o null (C #), el método no contiene el atributo.

private static bool IsAsyncMethod(Type classType, string methodName) { // Obtain the method with the specified name. MethodInfo method = classType.GetMethod(methodName); Type attType = typeof(AsyncStateMachineAttribute); // Obtain the custom attribute for the method. // The value returned contains the StateMachineType property. // Null is returned if the attribute isn''t present for the method. var attrib = (AsyncStateMachineAttribute)method.GetCustomAttribute(attType); return (attrib != null); }