C# 获取任务的方法名称

C# 获取任务的方法名称,c#,task,task-parallel-library,C#,Task,Task Parallel Library,我希望从C#中的任务中获取方法/操作名称。具体地说,我正在实现一个自定义任务调度器,并希望生成任务运行持续时间的统计信息,然后通过在任务内部运行的方法进行聚合。在VisualStudio调试器中,您可以访问它并查看m_action私有变量,以及调试器显示注释,将其显示为Method={0}。是否有任何方法可以从任务本身访问它 尝试反射以获取m_动作变量 尝试从任务内部的envoriment.StackTrace获取信息,或直接由其调用方法 您可以从任务中继承,使这变得非常简单。。。我将在这里为示

我希望从C#中的任务中获取方法/操作名称。具体地说,我正在实现一个自定义任务调度器,并希望生成任务运行持续时间的统计信息,然后通过在任务内部运行的方法进行聚合。在VisualStudio调试器中,您可以访问它并查看m_action私有变量,以及调试器显示注释,将其显示为Method={0}。是否有任何方法可以从任务本身访问它

  • 尝试反射以获取m_动作变量
  • 尝试从任务内部的
    envoriment.StackTrace
    获取信息,或直接由其调用方法

  • 您可以从任务中继承,使这变得非常简单。。。我将在这里为示例实现第一个构造函数:

    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) {}
    }
    
    更多的例子。从
    任务继承

        var fieldInfo = typeof(Task).GetField("m_action", BindingFlags.Instance | BindingFlags.NonPublic);
        Delegate action = fieldInfo.GetValue(task) as Delegate;
    
    公共类名称任务:任务{
    公共字符串MethodName{get;set;}
    公共名称任务(Func函数):基(函数){
    MethodName=function.Method.Name;
    }
    public-NamedTask(Func函数,string-methodName):base(函数){
    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"
    
    namedTask2=新的NamedTask(()=>{
    //一些任意代码
    返回true;
    });
    NamedTask任务3=新的NamedTask(()=>{
    //一些任意代码
    返回true;
    }“返回法”);
    字符串methodName2=task2.MethodName;//返回“b__19”
    字符串methodName3=task3.MethodName;//返回“returnTrueThod”
    
    好吧,如果给定一个
    任务
    变量
    任务
    ,您可以使用反射来获取私有
    m_action
    字段:

        var fieldInfo = typeof(Task).GetField("m_action", BindingFlags.Instance | BindingFlags.NonPublic);
        Delegate action = fieldInfo.GetValue(task) as Delegate;
    
    然后获取方法的
    名称
    ,以及
    去极化类型

        var name = action.Method.Name;
        var type = action.Method.DeclaringType.FullName;
    
    要获取完全限定的方法(
    type+“+name


    但是,一旦任务执行到完成,
    m_action
    即为
    null
    。我不确定这将如何应用于TaskFactory.StartNew…

    问题是,这将有多有用。您(通常)传递给
    任务的lambda表达式将由C#编译器转换为方法,并获取编译器生成的名称。这些名称不是,很难将它们与实际代码重新关联。@Christian.K如果您可以将自己限制为非常简单的lambda,您可以使用
    表达式来代替委托,并从中获取方法名称。(当然,
    表达式
    可以调用多个方法,因此您必须以某种方式选择要显示的方法。它也可能不调用任何方法。)有趣的想法。除:1
    MethodInfo.ToString()
    不仅返回方法name,还返回整个签名。例如,类似于
    Void asynchmethod()
    的内容。要仅获取名称,请使用
    name
    属性。2.正如Christian在评论中指出的,这不会给lambdas带来有用的结果。这是好的观点。对于#1,如果确实只需要方法名,可以从签名中解析它。对于#2,在我的示例中,我使用了lambda。。。所以我想也许你的意思是它不会给匿名方法带来任何有用的东西?在这种情况下,它仍然会返回一个方法名——它只是编译器为匿名方法生成的方法名。在这里,您可以创建另一个构造函数,允许您在创建任务时为匿名方法指定自己的名称。正如我所说,您可以使用
    name
    属性,无需解析任何内容。啊,action.method.name。对不错。我将改变帖子以反映这一点。
        var name = action.Method.Name;
        var type = action.Method.DeclaringType.FullName;