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
aDecimal?
这两个属性是不同的,但是如果它们在代码中各自设置了另一个属性,那么您仍然有无限递归,它只是永远在两个设置器之间切换,这一项是由EntityFramework创建的EntityObject。它的setter没有引用这个setter,您不需要windbg或PerfMon或任何其他特殊工具,只需使用VS调试器!通过堆栈跟踪、断点和分步调试,您可以了解发生了什么。我无法一步一步地完成。当我跨过指定的线时,它就断了。此外,SavedWork是EntityObject,因此它实际上没有更改的属性。我会将哪些订阅内容发布到PropertyChanged,但实际上并没有那么远。@ExitMusic最有可能