Showing posts with label delegate. Show all posts
Showing posts with label delegate. Show all posts

Monday, March 7, 2011

Tasks and anonymous delegates in for loops

Today at work I found a problem with using annonamous delagates tasks and foreach. Below is the code

List waitingSkills = new List();
foreach (var si in AgentSkills)
{
var t = Task.Factory.StartNew(delegate
{
try
{
si.Value.Dispositions = GetDispositions(si.Value.SkillNo);
}
catch (Exception ex)
{ ...
}

});

waitingSkills.Add(t);
}

var done = false;

while (!done)
{
done = true;
for (int i = 0; i < waitingSkills.Count; i++)
{
if (!waitingSkills[i].IsCompleted)
{
done = false;
Thread.Sleep(100);
break;
}

}

}

---------------------------------
The problem is that the value of si is the local value or last value assigned before the task kicks off. In my case the value was always the last value in the AgentSkills collection.

Here is the refactor. I got there by using this example found in Introducing Visual C# 2010

public void ProcessUpdateSkillsEvent(UpdateAgentSkillsEvent e)
{
ReskillSkills = new Dictionary();
AgentSkills = new Dictionary();

e.ReskillSkills.Where(r => r.SkillType == "Inbound").ToList().ForEach(rs => ReskillSkills.Add(rs.ID, ConvertAgentSkillToISkillItem(rs)));
e.Skills.ToList().ForEach(rs => AgentSkills.Add(rs.ID, ConvertAgentSkillToISkillItem(rs)));

var listOfSkills = AgentSkills.Values.ToList();
var waitingSkills = new Task[AgentSkills.Count];

//Create a func so we can pass the skillItem to the method so we can load the dispositions in a seperate thread.
Func funcGetDispositions = FuncGetDispositions;
for (int i = 0; i < listOfSkills.Count; ++i)
{
waitingSkills[i] = Task.Factory.StartNew(funcGetDispositions, listOfSkills[i]);
}

Task.WaitAll(waitingSkills.ToArray());

if (OnAgentSkillsUpdated != null)
OnAgentSkillsUpdated(AgentSkills.Values.ToList());

if (OnReskillSkillsUpdated != null)
OnReskillSkillsUpdated(ReskillSkills.Values.ToList());
}

public SkillItem FuncGetDispositions(object obj)
{
var skill = (SkillItem) obj;
try
{
skill.Dispositions = GetDispositions(skill.SkillNo);
}
catch (Exception ex)
{...
}
return skill;

}