我想包装Task类,但是当我运行我的代码时,它会抛出ArgumentOutOfRangeException。这很奇怪,因为当我使用调试器时,没有抛出任何异常。 这是我的代码的“工作”示例。
public class TaskService
{
private Task<int>[] _tasks;
private List<DateTime> _arguments = new List<DateTime>();
public void AddArgument(DateTime argument)
{
_arguments.Add(argument);
}
public void RunTask(Func<DateTime, int> doWork)
{
_tasks = new Task<int>[_arguments.Count];
for (int i = 0; i < _arguments.Count; i++)
{
_tasks[i] = Task.Factory.StartNew<int>(() => doWork(_arguments[i])); // Exception is throwing here: _arguments[i]
// by some reason i = 2, but _arguments.Count = 2 so it should never happed
}
}
public void Wait()
{
Task.WaitAll(_tasks);
}
}
class Program
{
static void Main(string[] args)
{
TaskService taskService = new TaskService();
taskService.AddArgument(new DateTime(2014, 1, 1));
taskService.AddArgument(new DateTime(2014, 2, 1));
taskService.RunTask(DoWork);
taskService.Wait();
}
public static int DoWork(DateTime day)
{
Console.WriteLine(day);
return 0;
}
}
答案 0 :(得分:3)
由于关闭(further reading),您的问题就出现了。 i
变量在lambda中捕获。完成创建任务后(循环后)i
的值为2
。当任务开始时,他们仍然指的是这个特定的int
实例。试试这个:
public void RunTask(Func<DateTime, int> doWork)
{
_tasks = new Task<int>[_arguments.Count];
for (int i = 0; i < _arguments.Count; i++)
{
var index = i;
_tasks[i] = Task.Factory.StartNew<int>(() => doWork(_arguments[index]));
}
}