Getting the method name of a task

2019-07-04 20:34发布

I am looking to get the method/action name from a task in C#. Specifically I am implementing a custom task scheduler, and would like to generate statistics on the duration a task runs, which I will then aggregate by the method running inside of the task. In the visual studio debugger you can access this and see the m_action private variable, as well as the debugger display annotation, displays it as Method={0}. Is there any way to get access to this from the Task itself?

3条回答
Anthone
2楼-- · 2019-07-04 21:20
  1. Try reflection to get m_action variable.
  2. Try getting info from Envorinment.StackTrace from inside the task or directly called methods by it.
查看更多
趁早两清
3楼-- · 2019-07-04 21:23

You could inherit from Task to make this real easy... I'm just going to implement the first constructor here for the example:

public class NamedTask : Task {
    public string MethodName { get; set; }
    public NamedTask(Action action) : base(action) {
        MethodName = action.Method.Name;
    }
    public NamedTask(Action action, CancellationToken cancellationToken) : base(action, cancellationToken) {}
    public NamedTask(Action action, TaskCreationOptions creationOptions) : base(action, creationOptions) {}
    public NamedTask(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions) : base(action, cancellationToken, creationOptions) {}
    public NamedTask(Action<object> action, object state) : base(action, state) {}
    public NamedTask(Action<object> action, object state, CancellationToken cancellationToken) : base(action, state, cancellationToken) {}
    public NamedTask(Action<object> action, object state, TaskCreationOptions creationOptions) : base(action, state, creationOptions) {}
    public NamedTask(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) : base(action, state, cancellationToken, creationOptions) {}
}

After that...

NamedTask task = new NamedTask(() => AsyncMethod(arg1, arg2, argN));
string methodName = task.MethodName; // there's the name!

More examples. Inherit from Task<T>:

public class NamedTask<T> : Task<T> {
    public string MethodName { get; set; }
    public NamedTask(Func<T> function) : base(function) {
        MethodName = function.Method.Name;
    }
    public NamedTask(Func<T> function, string methodName) : base(function) {
        MethodName = methodName;
    }
    ...
}

Handle anonymous methods:

NamedTask<bool> task2 = new NamedTask<bool>(() => {
                // some arbitrary code
                return true;
    });

NamedTask<bool> task3 = new NamedTask<bool>(() => {
                // some arbitrary code
                return true;
    }, "ReturnTrueMethod");

string methodName2 = task2.MethodName; // returns "<LongRunning_Async>b__19"
string methodName3 = task3.MethodName; // returns "ReturnTrueMethod"
查看更多
Juvenile、少年°
4楼-- · 2019-07-04 21:33

Well, you could use reflection to get at the private m_action field, given a Task variable task:

    var fieldInfo = typeof(Task).GetField("m_action", BindingFlags.Instance | BindingFlags.NonPublic);
    Delegate action = fieldInfo.GetValue(task) as Delegate;

Then get the Name of the method and the DeclaringType:

    var name = action.Method.Name;
    var type = action.Method.DeclaringType.FullName;

To get the fully qualified method (type + "." + name)...

But, as soon as the task executes to completion, m_action is null. I'm not sure how this would apply with TaskFactory.StartNew...

查看更多
登录 后发表回答