4
注:我不是说这是一个好想法,只是试图找出是否有比这蛮力一个“好”的选择。比手动字典更好的选项来引用方法在里面运行的'当前任务'?
这在以前想出了SO线程@How to get the current task reference?
然而,该线程是由一个特定的接口多一点约束。
蛮力的方法,我赶紧扔在一起,只使用弱引用的字典。
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);
}
}
}
}
然而,这显然意味着无论是创建任务被迫处理这个额外的头痛,所以它不是非常实用,在不那么明确创建任务特别WRT C#5异步方法。
再次,可能是一个坏主意,有需要的代码,所以认为它更像是一个思想的锻炼。 :)
如果你不知道这是一个好主意,那你为什么要做呢? – svick 2012-03-24 23:19:36
另外,我认为你不能使它成为异步友好的C#5,因为在异步方法中'Task.CurrentId'返回'null'。 – svick 2012-03-24 23:26:01
@svick - 迷人的 - 我也没有想到CurrentId是在异步方法无效(当然,第一的await后)。知道为什么会发生? – 2012-03-25 04:21:17