如何在TPL中为任务指定名称

meh*_*dvd 20 c# task-parallel-library parallel.foreach

我将在我的应用程序上运行许多任务.由于某种原因,每组任务都在运行.我想命名这些任务,所以当我观看Parallel Tasks窗口时,我可以轻松识别它们.

从另一个角度来看,考虑我在框架级别使用任务来填充列表.使用我的框架的开发人员也在为她的工作使用任务.如果她查看并行任务窗口,她会发现一些不知道的任务.我想命名任务,以便她可以将框架任务与她的任务区分开来.

如果有这样的API会很方便:

var task = new Task(action, "Growth calculation task")
Run Code Online (Sandbox Code Playgroud)

或者可能:

var task = Task.Factory.StartNew(action, "Populating the datagrid")
Run Code Online (Sandbox Code Playgroud)

甚至在工作时 Parallel.ForEach

Parallel.ForEach(list, action, "Salary Calculation Task"
Run Code Online (Sandbox Code Playgroud)

可以命名任务吗?

是否有可能得到Parallel.ForEach一个命名结构(也许使用Lambda),所以它创造了这样的命名任务?

我错过了某个地方的API吗?


我还尝试使用继承的任务来覆盖它的ToString().但不幸的是,Parallel Tasks窗口不使用ToString()!

class NamedTask : Task
{
    private string TaskName { get; set; }
    public NamedTask(Action action, string taskName):base(action)
    {
        TaskName = taskName;
    }

    public override string ToString()
    {
        return TaskName;
    }
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*erk 25

您可以将任何对象与任何对象相关联.这是Task的扩展.它使用WeakReference,因此当所有引用都超出范围时,仍然可以对任务进行垃圾回收.

用法:

var myTask = new Task(...
myTask.Tag("The name here");
var nameOfTask = (string)myTask.Tag();
Run Code Online (Sandbox Code Playgroud)

扩展类:

public static class TaskExtensions
{
    private static readonly Dictionary<WeakReference<Task>, object> TaskNames = new Dictionary<WeakReference<Task>, object>(); 

    public static void Tag(this Task pTask, object pTag)
    {
        if (pTask == null) return;
        var weakReference = ContainsTask(pTask);
        if (weakReference == null)
        {
            weakReference = new WeakReference<Task>(pTask);
        }
        TaskNames[weakReference] = pTag;
    }

    public static object Tag(this Task pTask)
    {
        var weakReference = ContainsTask(pTask);
        if (weakReference == null) return null;
        return TaskNames[weakReference];
    }

    private static WeakReference<Task> ContainsTask(Task pTask)
    {
        foreach (var kvp in TaskNames.ToList())
        {
            var weakReference = kvp.Key;

            Task taskFromReference;
            if (!weakReference.TryGetTarget(out taskFromReference))
            {
                TaskNames.Remove(weakReference); //Keep the dictionary clean.
                continue;
            }

            if (pTask == taskFromReference)
            {
                return weakReference;
            }
        }
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 真的很喜欢这个,但为什么不使用 ConcurrentDictionary 呢? (3认同)

svi*_*ick 6

你不能真正命名Task,但你可以命名由a执行的方法,Task然后在并行任务窗口中显示.因此,如果命名Tasks对您很重要,请不要使用lambdas,使用常规命名方法.

出人意料的是,这个工程即使有Parallel,即使在Task不直接执行你的方法.我认为这是因为Parallel Tasks以某种方式知道Tasks Parallel并以不同方式处理它们.

  • 这很好,但在很多情况下,当你有多个任务执行相同的方法时,这无论如何都不是很有用 (6认同)