C# 没有无限循环的堆栈溢出异常(据我所知)

C# 没有无限循环的堆栈溢出异常(据我所知),c#,wpf,xaml,entity-framework-4,stack-overflow,C#,Wpf,Xaml,Entity Framework 4,Stack Overflow,我有一个堆栈溢出错误,我相当确定我没有任何类型的无限递归(至少我已经盯着这个错误看了几个小时了,我无法想象它是如何无限循环的) 代码如下: public decimal? Amount { get { if (!string.IsNullOrEmpty(_savedWork.Amount)) return decimal.Parse(_savedWork.Amount);

我有一个堆栈溢出错误,我相当确定我没有任何类型的无限递归(至少我已经盯着这个错误看了几个小时了,我无法想象它是如何无限循环的)

代码如下:

    public decimal? Amount
    {
        get
        {
            if (!string.IsNullOrEmpty(_savedWork.Amount))
                return decimal.Parse(_savedWork.Amount);
            else
                return null;
        }
        set
        {
            if (value.HasValue)
            {
                _savedWork.Amount = value.Value.ToString();
                Percent = null;
            }
            else
                _savedWork.Amount = "";
            OnPropertyChanged("Amount");
        }
    }
#注意,我有一个包含在可空小数中的字符串,这就是我转换它的原因。请不要逼我解释我为什么要这样做。

savedWork.Amount=value.value.ToString()
是我得到错误的地方

基本上,我认为我的堆栈太小(或者我的代码太大)我基本上运行了两次这段代码,在一个表单中运行时有效,但在我创建另一个表单并将其放入其中时无效,因此我认为这两个表单之间的区别在于堆栈倾斜。

有没有办法确定我做错了什么?我想知道代码的哪一部分占用了太多的时间或者持续时间太长等等

我已经做了一些关于堆栈/堆如何工作的研究,我知道PerfMon.exe,但据我所知,它只对堆起作用。有没有类似的工具可以用于我的程序正在运行的堆栈

我找到了大约两个名为windbg和cdb的工具,但我找不到多少关于如何安装/使用它们的信息。这些工具正确吗

或者,如果有一个无限循环或是一些很棒的东西

编辑 这是Amount属性(由EntityFramework自动生成)所需的代码,正如我在评论中所说的,进入的步骤甚至没有到达这里。我真的认为我的堆栈限制刚刚达到

  public global::System.String Amount
    {
        get
        {
            return _Amount;
        }
        set
        {
            OnAmountChanging(value);
            ReportPropertyChanging("Amount");
            _Amount = StructuralObject.SetValidValue(value, true);
            ReportPropertyChanged("Amount");
            OnAmountChanged();
        }
    }
最终编辑 好的,所以元骑士的回答告诉我,我确实有一个无限循环。我让一个事件处理程序订阅了DisplayTypeOfInvestment(Amount属性所属的类)的PropertyChanged事件。处理程序如下所示:

 void DisplayTypeOfInvestmentList_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
            _typeOfInvestmentFormSavedWork.TypeOfInvestment.Clear();
            foreach (DisplayInvestmentFund d in _displayInvestmentFundList)
            {
                _typeOfInvestmentFormSavedWork.TypeOfInvestment.Add(d.SavedWork);
            }

            OnPropertyChanged("TypeOfInvestmentFormSavedWork");

    }
 void DisplayTypeOfInvestmentList_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Amount" || e.PropertyName == "Percent")
        {
            _savedWork.TypeOfInvestment.Clear();
            foreach (DisplayInvestmentFund d in _displayInvestmentFundList)
            {
                _savedWork.TypeOfInvestment.Add(d.SavedWork);
            }

            OnPropertyChanged("CurrentWork");
        }
    }
TypeOfInvestmentFormSavedWork
是一个完全不同的类,其中包含我们看到的用于Amount属性的SavedWork类的自身版本。此方法的要点是在Amount属性更改时,将此TypeOfInvestmentFormSavedWork属性更新为新值_savedWork。出于某种原因,这会触发DisplayTypeOfInvestment viewmodel的PropertyChanged。我没有弄明白,但我改变了方法,使其看起来像这样:

 void DisplayTypeOfInvestmentList_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
            _typeOfInvestmentFormSavedWork.TypeOfInvestment.Clear();
            foreach (DisplayInvestmentFund d in _displayInvestmentFundList)
            {
                _typeOfInvestmentFormSavedWork.TypeOfInvestment.Add(d.SavedWork);
            }

            OnPropertyChanged("TypeOfInvestmentFormSavedWork");

    }
 void DisplayTypeOfInvestmentList_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Amount" || e.PropertyName == "Percent")
        {
            _savedWork.TypeOfInvestment.Clear();
            foreach (DisplayInvestmentFund d in _displayInvestmentFundList)
            {
                _savedWork.TypeOfInvestment.Add(d.SavedWork);
            }

            OnPropertyChanged("CurrentWork");
        }
    }
调用Add方法时,if语句停止DisplayInvestmentFund中正在更改的奇怪属性


我意识到这个答案没有多大意义,但对我来说,详细解释这个问题需要很长时间。我也意识到这可能意味着我的代码不好。我不知道该怎么办。谢谢大家的帮助。

我猜您是在
OnPropertyChanged
调用的一个事件处理程序中分配给
金额

另一种可能性是,
SavedWork.Amount
的setter中有代码,再次调用
YourClass.Amount


但是你为什么不调试一下呢?只需在VisualStudio调试器中逐步完成代码

堆栈跟踪也应该很有用。使用无休止的递归,通常会得到一系列重复的方法。如果我的猜测是正确的,那么重复的部分将类似于:

MyClass.set_Amount
MyClass.OnPropertyChanged
OtherClass.myClass_amount_changed

哪个Amount成员的类与_savedWork的类型相同

因为可能有这个循环:

1) 您为金额指定了一个值

2) 在设置该值之前,请为_savedWork.Amount指定一个值

3) 在设置_savedWork.Amount的值之前,将再次触发该行

4) 在设置_savedWork._savedWork.Amount的值之前

5) 在设置_savedWork._savedWork._savedWork.Amount的值之前


这是无限远的。

保存的工作
是与您列出的
金额
属性类型相同的对象吗?因为这会导致堆栈溢出错误!在这种情况下,您需要找到一种方法来谈论
Amount
,而不调用
get
ter和
set
ter。

必须以某种方式递归调用
Amount
setter。您可以通过“单步执行”属性而不是单步执行来调试它。如果您设置了VS,使其不进入属性,您仍然可以在设置程序中设置断点,以模拟“进入”过程。至于没有进入.edmx文件的VS,正如CodeInChaos所提到的,可能该类被标记了一个属性。

您是否已通过代码确认没有无限递归?您的OnPropertyChanged(“Amount”)是什么;?什么是
\u保存的工作
?它是这个类的一个实例,还是包含这个类的一个成员?闻起来也像是无限的递归。如果没有额外的信息,很难判断发生了什么。什么类型是_savedWork,什么类型是成员的当前属性等。由于
_savedWork.Amount
是一个字符串,它显然是一个不同的类。
_savedWord!=这是
\u savedWork.Amount
是一个字符串,
value.Amount
a
Decimal?
这两个属性是不同的,但是如果它们在代码中各自设置了另一个属性,那么您仍然有无限递归,它只是永远在两个设置器之间切换,这一项是由EntityFramework创建的EntityObject。它的setter没有引用这个setter,您不需要windbg或PerfMon或任何其他特殊工具,只需使用VS调试器!通过堆栈跟踪、断点和分步调试,您可以了解发生了什么。我无法一步一步地完成。当我跨过指定的线时,它就断了。此外,SavedWork是EntityObject,因此它实际上没有更改的属性。我会将哪些订阅内容发布到PropertyChanged,但实际上并没有那么远。@ExitMusic最有可能