23

アプリケーションで実行されている多くのタスクを使用します。何らかの理由で一連のタスクが実行されています。これらのタスクに名前を付けて、[並列タスク] ウィンドウを見たときに簡単に認識できるようにします。

別の観点から、フレームワーク レベルでタスクを使用してリストを作成していると考えてください。私のフレームワークを使用する開発者は、自分の仕事にもタスクを使用しています。彼女が Parallel Tasks ウィンドウを見ると、いくつかのタスクについて何も知らないことがわかります。彼女がフレームワーク タスクと自分のタスクを区別できるように、タスクに名前を付けたいと思います。

こんなAPIがあればとても便利です。

var task = new Task(action, "Growth calculation task")

または多分:

var task = Task.Factory.StartNew(action, "Populating the datagrid")

または作業中もParallel.ForEach

Parallel.ForEach(list, action, "Salary Calculation Task"

タスクに名前を付けることは可能ですか?

‍‍‍‍<code>Parallel.ForEach に名前付け構造 (おそらくラムダを使用) を与えて、その名前付けでタスクを作成することは可能ですか?

私が行方不明になっているような API はどこかにありますか?


また、継承されたタスクを使用して ToString() をオーバーライドしようとしました。残念ながら、並列タスク ウィンドウは 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;
    }
}
4

11 に答える 11

32

任意のオブジェクトを任意のオブジェクトに関連付けることができます。これは Task の拡張です。WeakReference を使用するため、すべての参照がスコープ外の場合でも、タスクをガベージ コレクションできます。

使用法:

var myTask = new Task(...
myTask.Tag("The name here");
var nameOfTask = (string)myTask.Tag();

拡張クラス:

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;
    }
}
于 2015-12-22T14:54:48.957 に答える
11

に実際に名前を付けることはできませんがTask、 によって実行されるメソッドに名前を付けることができますTask。これは、[並列タスク] ウィンドウに表示されます。したがって、Tasks に名前を付けることが重要な場合は、ラムダを使用せず、通常の名前付きメソッドを使用してください。

驚くべきことに、メソッドを直接実行していなくParallelても、これは で機能します。Taskこれは、Parallel Tasks が何らかの方法でTasks fromParallelを認識し、それらを異なる方法で処理するためだと思います。

于 2012-12-09T17:00:38.387 に答える
3

タスクに名前を付けることはできません。

タスク ライブラリは内部でスレッド プールを使用しているため、スレッドに名前を付けることはできません。また、「.ContinueWith()」などのメソッドは常に新しいタスクを作成し、クラスから継承しないため、継承アプローチは機能しません。

于 2012-12-07T13:36:50.193 に答える
1

Parallel Tasksウィンドウの動作がわからないため、ここではブラインドで撮影していますが、デバッガーAPIを使用している場合は、 NamedTaskサブクラスにDebuggerDisplay属性を追加すると役立つ場合があります。

于 2012-12-07T12:57:41.827 に答える
1

タスクに名前を付けることはできないと思います。Task.Idタスクの追跡に使用できます。

于 2012-12-07T11:40:23.203 に答える
0

マイクの答えのおかげで、私は次のようになりました:

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

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

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

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

                if (!weakReference.TryGetTarget(out var taskFromReference))
                {
                    TaskNames.TryRemove(weakReference, out _);
                    //TaskNames.TryRemove(out ); //Keep the dictionary clean.
                    continue;
                }

                if (pTask == taskFromReference)
                {
                    return weakReference;
                }
            }
            return null;
        }
    }

現在はスレッドセーフで、タグだけでなく名前もサポートしています。

于 2020-02-16T03:10:57.353 に答える
0
public class NamesTask {
    readonly Queue<Task> _taskqueue = new Queue<Task>();
    private readonly object _queueLock = new object();

    public Task RunTask(Action action) {
        //incoming task must be queued as soon as it arrives
        var inComingTask = new Task(action);

        lock (_queueLock) {
            _taskqueue.Enqueue(inComingTask);
        }

        return Task.Factory.StartNew(() => {
            //run all actions one by one..
            while (true) {
                lock (_queueLock) { //only one task must be performed at a 
                    if (_taskqueue.Count == 0) return;

                    var outTask = _taskqueue.Dequeue();

                    outTask.Start();
                    outTask.Wait();

                    Console.WriteLine("done....");
                }
            }
        });
    }
}
于 2016-04-21T11:37:16.577 に答える