2017-02-09 16 views
0

Я хочу получить имя этого метода, используя Отражение и т. Д. Я использую много вещей, но я устал, пожалуйста, помогите мне. Если функция синхронизирована, то код ниже будет работать нормально. Пожалуйста, перейдите к приведенному ниже коду, который очистит вас от моего вопроса.Как мы можем получить имя асинхронного метода В C#

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

Этот метод предоставьте мне имя метода non async. но как я получаю выше имя метода

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

Но этот метод работает только для не асинхронного метода. Итак, как получить текущее имя метода асинхронного программирования в C#

+0

Проблема заключается в том, что «стек» в вашем конкретном случае с использованием 'Task.Run' не является естественным стеком как таковым, поток threadpool был развернут для запуска вашего анонимного метода, как такового, стек не содержит ничего конкретного для метода 'GETNumber'. * Однако * в данном конкретном случае сгенерированное имя для вашего анонимного метода содержит имя, имя метода будет выглядеть как '. b__1_0'. –

+0

Теперь вопрос в том, для чего именно нужно имя? –

+0

Проверка: [Получить имя текущего метода из функции async] (http://stackoverflow.com/q/20158902/1351076) – krlzlx

ответ

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 методами (я не уверен, но я предполагаю, что аргумент заменяется на компиляции время).

+0

Сторона примечания - то же самое верно для методов итератора, которые приносят результаты. Хотя возможно ли получить имя метода, который содержит конечный автомат? –