Error in Parallel.ForEach - Object reference not set to an instance of an object
I have a strange problem that I am unable to debug. Here's a delegate that parses informa开发者_如何学Pythontion:
Action<XElement, String> ParseXMLInfo = (s, t) =>
{
using (var Ctx = new Entities())
{
var Records = s.Elements("record");
Parallel.ForEach(
ParallelEnumerable.Range(0, Records.Count()),
u =>
{
var el = Records.ElementAt(u);
try
{
var NTR = new tbl_UserInfo();
NTR.first_name = el.Element("first_name").Value;
NTR.last_name = el.Element("last_name").Value;
Ctx.AddTotbl_UserInfo(NTR);
}
catch (Exception excp)
{
Console.WriteLine(System.DateTime.Now + " " + excp.Message);
}
}
);
Ctx.SaveChanges();
}
};
The delegate itself is called twice, as follows:
Parallel.Invoke(
() =>
{
var XMLDoc_MaleInfo = XElement.Load("MaleNames.xml");
Console.WriteLine("Fetching records from MaleNames.xml; starting at " + System.DateTime.Now);
ParseXMLInfo(XMLDoc_MaleInfo, "male");
},
() =>
{
var XMLDoc_FemaleInfo = XElement.Load("FemaleNames.xml");
Console.WriteLine("Fetching records from FemaleNames.xml; starting at " + System.DateTime.Now);
ParseXMLInfo(XMLDoc_MaleInfo, "female");
}
);
Everything appears to run correctly. In particular, the Parallel.ForEach
portion of the delegate runs without any error. But then, the code breaks at the line Ctx.SaveChanges ()
, with the message
Object reference not set to an instance of an object.
But when I hover over Ctx
(in this broken state), Ctx
is not shown to be null
.
Can someone please tell me what is going on?
Think it should be:
ParallelEnumerable.Range (0, Records.Count()-1)
Okay, after much scanning through MSDN documentation, I appear to have come up with at least one solution for now. Here is the re-factored code.
Action<XElement, String> ParseXMLInfo = (s, t) => {
var Records = s.Elements ("record");
Parallel.ForEach (
ParallelEnumerable.Range (0, Records.Count ()),
() => new Testing_And_Benchmarking_Entities (),
(u, L, v) => {
var el = Records.ElementAt (u);
var NTR = new tbl_UserInfo ();
NTR.first_name = el.Element ("first_name").Value;
NTR.last_name = el.Element ("last_name").Value;
v.AddTotbl_UserInfo (NTR);
return v;
},
(v) => v.SaveChanges ()
);
};
Parallel.Invoke (
() => {
var XMLDoc_MaleInfo = XElement.Load ("MaleNames.xml");
Console.WriteLine ("Fetching records from MaleNames.xml; starting at " + System.DateTime.Now);
ParseXMLInfo (XMLDoc_MaleInfo, "male");
},
() => {
var XMLDoc_FemaleInfo = XElement.Load ("FemaleNames.xml");
Console.WriteLine ("Fetching records from MaleNames.xml; starting at " + System.DateTime.Now);
ParseXMLInfo (XMLDoc_FemaleInfo, "female");
}
);
I had to use a different overloaded signature of Parallel.ForEach. In this overload, the equivalent to the Ctx variable in the previous example ("v" in this example, please pardon the cryptic variable names) is not shared. So the error is avoided.
I would still appreciate a comment from someone knowledgeable as to whether my solution is the only one, or whether there is a better, more idiomatic C# solution.
精彩评论