Performing multiple tasks reuses the same instance of an object

Here is an interesting one. I have a service creating a bunch of Task s. Currently, only two tasks are configured in the list. However, if I put a breakpoint in the Task action and check the schedule.Name value, it twice falls into the same schedule name. However, two separate schedules are configured and listed on the schedule list. Can someone explain why the task reuses the last schedule in the loop? Is this a problem with the area?

 // make sure that we can log any exceptions thrown by the tasks TaskScheduler.UnobservedTaskException += new EventHandler<UnobservedTaskExceptionEventArgs>(TaskScheduler_UnobservedTaskException); // kick off all enabled tasks foreach (IJobSchedule schedule in _schedules) { if (schedule.Enabled) { Task.Factory.StartNew(() => { // breakpoint at line below. Inspecting "schedule.Name" always returns the name // of the last schedule in the list. List contains 2 separate schedule items. IJob job = _kernel.Get<JobFactory>().CreateJob(schedule.Name); JobRunner jobRunner = new JobRunner(job, schedule); jobRunner.Run(); }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default ); } } // next schedule 
+4
source share
1 answer

If you use a temporary variable inside the foreach loop, it should solve your problem.

 foreach (IJobSchedule schedule in _schedules) { var tmpSchedule = schedule; if (tmpSchedule.Enabled) { Task.Factory.StartNew(() => { // breakpoint at line below. Inspecting "schedule.Name" always returns the name // of the last schedule in the list. List contains 2 separate schedule items. IJob job = _kernel.Get<JobFactory>().CreateJob(tmpSchedule.Name); JobRunner jobRunner = new JobRunner(job, tmpSchedule); jobRunner.Run(); }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default ); } } // 

For more information on closures and loop variables, see Closing a loop variable that is considered harmful.

+5
source

All Articles