How can I tell if a C# method is async/await via reflection?

匿名 (未验证) 提交于 2019-12-03 01:59:02

问题:

e.g.

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

If we are reflecting over this class and method, how can I determine if this is an actual async/await method rather than simply a method that happens to return a Task?

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

回答1:

In my copy of your code, the MethodInfo for the async method contains the following items in the CustomAttributes property:

  • a DebuggerStepThroughAttribute
  • a AsyncStateMachineAttribute

whereas the MethodInfo for the normal method contains no items in its CustomAttributes property.

It seems like the AsyncStateMachineAttribute should reliably be found on an async method and not on a standard one.

Edit: In fact, that page even has the following in the examples!

As the following example shows, you can determine whether a method is marked with Async (Visual Basic) or async (C# Reference) modifier. In the example, IsAsyncMethod performs the following steps:

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); } 


回答2:

Here's an example of two methods, and I'm asking you why you think that they should be treated differently:

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

They both have, to within a handwave, the exact same runtime behaviour - for 20 seconds they do nothing (and don't hold onto a thread during that period) and then they run a small delegate that just passes back the value that was initially passed to the method.

And yet, you're going to treat one vastly differently from the other because I choose to use the compiler to hide some of the plumbing?



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!