Parallel.ForEach 中的错误 - 未将对象引用设置为对象的实例

发布于 2024-10-28 00:28:09 字数 1699 浏览 1 评论 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

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

I have a strange problem that I am unable to debug. Here's a delegate that parses information:

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一指流沙 2024-11-04 00:28:09

觉得应该是:

ParallelEnumerable.Range (0, Records.Count()-1)

Think it should be:

ParallelEnumerable.Range (0, Records.Count()-1)
ヅ她的身影、若隐若现 2024-11-04 00:28:09

好吧,经过大量浏览 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# 解决方案的评论。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文