【问题标题】:How We Can get the async Method Name In c# [duplicate]我们如何在c#中获取异步方法名称[重复]
【发布时间】:2017-02-09 21:26:37
【问题描述】:

我想通过使用 Reflection 等来获取此方法的名称...我使用了很多东西但我很累请帮助我。 如果该功能是同步的,那么它下面的代码将正常工作。请仔细阅读下面的代码,这将解决您的问题。

// this will work fine
public void Test()
{
// This GetCurrentMethod() will you the name of current method
string CurrentMethodName = GetCurrentMethod();
// output will be CurrentMethodName = Test
}


// this will not work
      public async Task<int> GETNumber(long ID)
      {
// This GetCurrentMethod() will you the name of current method if the method is sync or not async
string CurrentMethodName = GetCurrentMethod();
           return await Task.Run(() => { return 20; });
      }

此方法为我提供非异步方法的名称。但是我如何获得上述方法名称

>     [MethodImpl(MethodImplOptions.NoInlining)]
>           public static string GetCurrentMethod()
>           {
>                 var stackTrace = new StackTrace();
>                 StackFrame stackFrame = stackTrace.GetFrame(1);
>                 return stackFrame.GetMethod().Name;
>           }

但此方法仅适用于非异步方法。那么如何在c#中获取当前的异步方法名称

【问题讨论】:

  • 这里的问题是,在您的特定情况下,使用Task.Run 的“堆栈”不是自然堆栈,因此已经启动了一个线程池线程来运行您的匿名方法,因此,堆栈不包含任何特定于 GETNumber 方法的内容。 但是,在这种特殊情况下,为您的匿名方法生成的名称包含该名称,该方法的名称将类似于.&lt;GETNumber&gt;b__1_0。
  • 现在,问题是,你到底需要这个名字做什么?
  • 副本仅对您的特定情况有效,但是,它涉及匿名方法或 lambda 表达式。如果您的异步方法是普通方法,则此方法不起作用。你确定nameof(GETNumber) 不会成功吗?

标签: c# asp.net asp.net-mvc c#-4.0 c#-3.0


【解决方案1】:

你想要的实际上是不可能的。编译器为async 方法创建一个状态机,类似这样的

public class GetNumberStateMachine : IAsyncStateMachine
{
    // ....
    void IAsyncStateMachine.MoveNext()
    {
        // here your actual code happens in steps between the 
        // await calls
    }
}

并将您的方法转换为类似的东西:

public async Task<int> GetNumber()
{
     GetNumberStateMachin stateMachine = new GetNumberStatemachine();
     stateMachine.\u003C\u003Et__builder = AsyncTaskMethodBuilder<int>.Create();
     stateMachine.\u003C\u003E1__state = -1;
     stateMachine.\u003C\u003Et__builder.Start<GetNumberStatemachine>(ref stateMachine);
     return stateMachine.\u003C\u003Et__builder.Task;
}

所以在运行时调用您的GetCurrentMethod() 不再是您的GetNumber()。


但是你可以通过CallerMemberNameAttribute获取调用方法的名称:

public static string GetCurrentMethod([CallingMemberName] string method = "")
{
     return method;
}

public async Task<int> GetNumber(long ID)
{
   int result = await Task.Run(() => { return 20; });
   Console.WriteLine(GetCurrentMethod()); // prints GetNumber
   return result;
}

这甚至适用于 async 方法(我不确定,但我猜这个参数在编译时被替换了)。

【讨论】:

  • 旁注 - 对于产生结果的迭代器方法也是如此。虽然仍然可以获得包含状态机的方法的名称吗?
猜你喜欢
  • 1970-01-01
  • 2021-12-04
  • 2021-02-09
  • 2015-02-24
  • 2023-03-11
  • 2012-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多