获取任务的方法名

问题描述 投票:0回答:4

我希望从 C# 任务中获取方法/操作名称。具体来说,我正在实现一个自定义任务调度程序,并且希望生成有关任务运行持续时间的统计信息,然后我将通过任务内部运行的方法来汇总这些统计信息。在 Visual Studio 调试器中,您可以访问它并查看 m_action 私有变量,以及调试器显示注释,将其显示为 Method={0}。有什么方法可以从任务本身访问它吗?

c# task task-parallel-library
4个回答
4
投票

您可以继承 Task 以使这变得非常简单...我将在这里实现第一个构造函数作为示例:

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

之后...

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

更多示例。继承自

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

处理匿名方法:

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"

3
投票

好吧,你可以使用反射来获取私有

m_action
字段,给定一个
Task
变量
task
:

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

然后获取方法的

Name
DeclaringType

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

要获得完全合格的方法(

type + "." + name
)...

但是,一旦任务执行完成,

m_action
就是
null
。我不确定这如何适用于 TaskFactory.StartNew...


0
投票
  1. 尝试反射来获取 m_action 变量。
  2. 尝试从任务内部的
    Envorinment.StackTrace
    获取信息或直接调用它的方法。

0
投票

这是在后台线程中使用异步任务唯一对我有用的东西:

private static string MethodName(this Task task)
{
    const string start = "+<";
    const string end = ">d__";

    var fullName = task.GetType().FullName;
    if (string.IsNullOrEmpty(fullName))
       return string.Empty;

    var methodName = fullName.Substring(fullName.IndexOf(start) + start.Length);
    return methodName.Remove(methodName.IndexOf(end));
}

希望它能有所帮助或提供想法。

© www.soinside.com 2019 - 2024. All rights reserved.