Better than a manual dictionary for referencing the "current task" that uses the method internally?

NOTE. I'm not saying this is a good idea, just trying to figure out if there is a β€œbetter” option than this brute force.

This appeared in a previous SO @ thread. How do I get the current job link?

However, this thread was a bit more limited by a specific interface.

The brute force approach I quickly got together with just uses a dictionary of weak links.

using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace GetCurrentTaskExample { public static class TaskContext { // don't need a ConcurrentDictionary since we won't be reading/writing the same task id with different tasks concurrently private static readonly Dictionary<int, WeakReference> s_indexedTaskReferences = new Dictionary<int, WeakReference>(); public static void AddAndStartTasks(IEnumerable<Task> tasks) { foreach (var task in tasks) { AddTask(task); task.Start(); } } public static void AddTask(Task task) { s_indexedTaskReferences[task.Id] = new WeakReference(task); } public static Task GetCurrentTask() { var taskId = Task.CurrentId; if (taskId == null) return null; WeakReference weakReference; if (s_indexedTaskReferences.TryGetValue(taskId.Value, out weakReference) == false) return null; if (weakReference == null) return null; // should not happen since we don't store null as a value var task = weakReference.Target as Task; return task; } } class Program { static void Main(string[] args) { var tasks = Enumerable.Range(0, 100) .Select(i => new Task(VerifyCurrentTaskWorks, i)) .ToArray(); TaskContext.AddAndStartTasks(tasks); Task.WaitAll(tasks); } static void VerifyCurrentTaskWorks(object instanceIdentifier) { var currentTask = TaskContext.GetCurrentTask(); if (currentTask.Id == Task.CurrentId) { Console.WriteLine("Verified for instance {0} that Task.CurrentId value of {1} matches Id property {2} of task {3}", instanceIdentifier, Task.CurrentId, currentTask.Id, currentTask); } else { var errorMessage = String.Format("TaskContext.GetCurrentTask() failed for instance {0} with Task.CurrentId value of {1} and currentTask.Id value of {2}", instanceIdentifier, Task.CurrentId, currentTask.Id); throw new InvalidOperationException(errorMessage); } } } } 

However, this clearly means that everything that creates the tasks is forced to deal with this additional headache, therefore it is not very useful, especially for the WRT C # 5 asynchronous methods, where the task is not so explicitly created.

Again, it might be a bad idea to have code that needs it, so consider it more like a mental exercise. :)

+4
source share
1 answer

There, unfortunately, there was no better way, and since the ultimate goal was to disable Task.CurrentId, it really is not even useful, since we will not be able to get the "current task identifier" for asynchronous methods (after the first wait, so that he has already returned to the caller).

0
source

Source: https://habr.com/ru/post/1403272/


All Articles