0

我有一个无法调试的奇怪问题。这是一个解析信息的委托:

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();
    }
};

委托本身被调用两次,如下所示:

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");
    }
);

一切似乎都运行正常。特别是,Parallel.ForEach委托的部分运行没有任何错误。但是随后,代码在该行中断Ctx.SaveChanges (),并显示消息

你调用的对象是空的。

但是当我将鼠标悬停在Ctx(处于这种破碎状态)时,Ctx不会显示为null.

有人可以告诉我发生了什么吗?

4

2 回答 2

0

认为应该是:

ParallelEnumerable.Range (0, Records.Count()-1)
于 2011-03-31T07:56:29.240 回答
0

好的,在浏览了 MSDN 文档之后,我现在似乎已经想出了至少一个解决方案。这是重构的代码。

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");
            }
        );

我不得不使用不同的 Parallel.ForEach 重载签名。在此重载中,不共享与上一个示例中的 Ctx 变量(本示例中的“v”,请原谅神秘的变量名称)等效的变量。因此避免了错误。

对于我的解决方案是否是唯一的解决方案,或者是否有更好、更惯用的 C# 解决方案,我仍然希望有知识渊博的人发表评论。

于 2011-03-31T09:03:28.763 回答