HINWEIS: Ich sage nicht, dass dies eine gute Idee ist, nur um herauszufinden, ob es eine "bessere" Option als diese Brute-Force-Option gibt.bessere Optionen als das manuelle Wörterbuch für die Referenzierung der 'aktuellen Aufgabe', in der eine Methode ausgeführt wird?
Dies kam in einem früheren SO gewinde @How to get the current task reference?
jedoch, dass Faden durch eine bestimmte Schnittstelle ein wenig eingeschränkt war.
Die Brute-Force-Ansatz, den ich zusammengeworfen schnell verwendet nur ein Wörterbuch der schwachen Referenzen.
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);
}
}
}
}
Dies bedeutet aber klar, was die Aufgaben schafft gezwungen ist, mit diesen zusätzlichen Kopfschmerzen zu behandeln, so ist es nicht sehr brauchbar, insbesondere WRT C# 5 Asynchron-Verfahren, bei denen die Aufgabe nicht so explizit erstellt.
Auch hier ist es wahrscheinlich eine schlechte Idee, einen Code zu haben, der dies benötigt, also denken Sie eher an eine Gedankenübung. :)
Wenn Sie nicht sicher sind, ob das eine gute Idee ist, warum versuchen Sie es dann? – svick
Auch, ich denke, Sie können es nicht C# 5 async-freundlich machen, weil 'Task.CurrentId' innerhalb einer asynchronen Methode' null' zurückgibt. – svick
@svick - faszinierend - Ich hätte nicht erwartet, dass CurrentId in einer asynchronen Methode null ist (naja, nach der ersten Wartezeit). Pass auf zu wissen, warum das so ist? –