c#设置+;栈溢出异常
在我的wpf应用程序中有一个usercontrol,它导致stackoverflowexception在多次实例化时被捕获。我试图调试异常的原因,它是在初始化Usercontrol的组件时引发的。当我输入InitializeComponent时,它跳转到app.xaml.cs codebeahind并读取Settings类中包含的值 我是“新”使用C#应用程序设置的人,所以我以前没有遇到过这个错误。不确定这在与他们一起工作时是否常见。此外,这是我的应用程序中当前唯一允许修改设置变量的用户控件,也是唯一显示此行为的用户控件 我认为我的问题与使用“Application.Current”的datacontext的DebugOptions类有关,然后我使用相同的datacontext创建了另一个实例,但一旦我访问了它的任何属性,我就会让应用程序混淆哪个obj是哪个。虽然这在我的头脑中是有道理的,但从逻辑上讲,它不是这样的,因为这个usercontrol在单击按钮时被实例化,并且在添加之前它的主机面板被清除,以防止多个实例滚动 下面是我的usercontrol的xaml和代码隐藏。除绑定到的应用程序类中的CLR属性外,它没有依赖项。我希望我能提供更多关于这方面的信息,但这是一个非常奇怪的例外 下面是my App类中的属性,当它被“Get”访问时,它会导致stackoverflow异常c#设置+;栈溢出异常,c#,wpf,stack-overflow,C#,Wpf,Stack Overflow,在我的wpf应用程序中有一个usercontrol,它导致stackoverflowexception在多次实例化时被捕获。我试图调试异常的原因,它是在初始化Usercontrol的组件时引发的。当我输入InitializeComponent时,它跳转到app.xaml.cs codebeahind并读取Settings类中包含的值 我是“新”使用C#应用程序设置的人,所以我以前没有遇到过这个错误。不确定这在与他们一起工作时是否常见。此外,这是我的应用程序中当前唯一允许修改设置变量的用户控件,也
private Byte _debuglevel = Merlin.Properties.Settings.Default.DebugLevel;
public Byte DebugLevel
{
get { return _debuglevel; }
set { _debuglevel = value; }
}
public partial class DebugOptions : UserControl
{
public DebugOptions()
{
InitializeComponent();
}
private void ChangeLogDirectoryButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
MessageBox.Show("Make a decision here...choose to use the old winforms folder browser control or find one on the web because the std openfiledialog can't be overriden to select folders only.", "Fix this..");
}
private void UpdateDebugOptionsButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
//update debug level
Merlin.Properties.Settings.Default.DebugLevel = (Byte)DebugLevelSlider.Value;
//update log boolean
if ((bool)EnableLoggingRadioButton.IsChecked)
{
Merlin.Properties.Settings.Default.LogsEnabled = true;
}
else
{
Merlin.Properties.Settings.Default.LogsEnabled = false;
}
//update log path?
//save "settings"
Merlin.Properties.Settings.Default.Save();
//write a log event noting changes
App myappreference = (App)Application.Current;
Merlin.Helper.logger.pLogToFile(string.Format("Log Settings Updated at {0} by {1}", DateTime.Now.ToString(), myappreference.CurrentUser.UserName));
}
private void OpenLogDirectoryButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
Process process = new Process();
Process.Start("Explorer.exe", Merlin.Properties.Settings.Default.LogsDirectory);
}
}
为简洁起见,省略了Usercontrol资源和Usercontrol标记
<Border BorderBrush="Black" BorderThickness="1" Margin="0">
<Grid DataContext="{Binding Source={x:Static Application.Current}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Content="Debug Options" HorizontalAlignment="Center" Margin="0" Grid.Row="0" VerticalAlignment="Center" FontSize="29.333" Style="{StaticResource UserControlTitleLabelStyle}" />
<StackPanel Orientation="Horizontal" Grid.Row="1">
<Label Content="Set Debug Level" HorizontalAlignment="Left" VerticalAlignment="Center"/>
<Slider x:Name="DebugLevelSlider" HorizontalAlignment="Left" VerticalAlignment="Center" Maximum="10" Value="{Binding DebugLevel}" Minimum="1" Margin="62,0,0,0" TickPlacement="BottomRight" SmallChange="1" Style="{StaticResource SliderStyle1}" Width="119">
<Slider.ToolTip>
<ToolTip Content="{Binding DebugLevel}" ContentStringFormat="{}The current value is {0} out of 10"/>
</Slider.ToolTip>
</Slider>
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Row="2">
<Label Content="Application Level Logging: " />
<RadioButton x:Name="EnableLoggingRadioButton" GroupName="Logs" Content="Enable" Margin="5" IsChecked="{Binding LogsEnabled}">
<RadioButton.ToolTip>
<TextBlock Text="Selecting this option will enable logs at the debug level selected above."/>
</RadioButton.ToolTip>
</RadioButton>
<RadioButton x:Name="DisableLoggingRadioButton" GroupName="Logs" Content="Disable" Margin="5" IsChecked="{Binding Path=IsChecked,ElementName=EnableLoggingRadioButton, Converter={StaticResource oppositebooleanconverter}}" >
<RadioButton.ToolTip>
<TextBlock Text="Selecting this option will disable all logs for the application."/>
</RadioButton.ToolTip>
</RadioButton>
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Row="3">
<Label Content="Log Path" HorizontalAlignment="Left" VerticalAlignment="Center" />
<TextBox Margin="10" Width="347.553" TextWrapping="Wrap" Text="{Binding LogsDirectory}" VerticalAlignment="Stretch" />
<StackPanel Height="100">
<Button x:Name="OpenLogDirectoryButton" Content="Open Directory" Width="100" Margin="0,10,0,0" VerticalAlignment="Center" HorizontalAlignment="Right" Style="{StaticResource ButtonStyle}" d:LayoutOverrides="GridBox" Click="OpenLogDirectoryButton_Click" />
<Button x:Name="ChangeLogDirectoryButton" Content="Change Directory" Width="100" Margin="0,10,0,0" VerticalAlignment="Center" HorizontalAlignment="Right" Style="{StaticResource ButtonStyle}" d:LayoutOverrides="GridBox" Click="ChangeLogDirectoryButton_Click" IsEnabled="False" />
</StackPanel>
</StackPanel>
<Button x:Name="UpdateDebugOptionsButton" Content="Update" Grid.Row="4" Width="100" VerticalAlignment="Center" HorizontalAlignment="Right" Style="{StaticResource ButtonStyle}" Click="UpdateDebugOptionsButton_Click" Margin="0,0,8,10" />
</Grid>
</Border>
抛出异常之前的Stacktrace
Merlin.exe!Merlin.App.LogsEnabled.set(布尔值=false)第52行C#
[外部代码]
Merlin.exe!Merlin.View.DebugOptions.DebugOptions()行25+0x8字节C#
[外部代码]
Merlin.exe!Merlin.View.TestView.TestView()行24+0x8字节C#
Merlin.exe!Merlin.MainWindow.SidebarButtonsClickHandler(对象发送方={Merlin.ImageButton},System.Windows.RoutedEventArgs e={System.Windows.RoutedEventArgs})第218行+0x15字节C#
[外部代码]
奇怪的是,在initializecomponent例程中,会获取“LogsEnabled”布尔值,然后立即调用以进行设置。我不知道怎么称呼它来设定它。但一旦它设置了值,它就会再次尝试获取它。我确信运行时抛出stackoverflow是为了防止无限循环。那么,我如何才能知道它为什么要这样做呢?堆栈溢出可能是由于循环定义的引用导致的:看起来可能发生这种情况的一种方式是滑块控件绑定到DebugLevel。但是,当您输入update方法时,它将DebugLevel的值定义为滑块控件的值 因此,您可能会得到如下结果: 滑块控件的值?哦,我去找找。 调试级别的值?哦,我去查一下滑块控件的值。 滑块控件的值?哦,我去找找 我不确定,但这可能是问题所在
(就像上面提到的注释一样,堆栈跟踪在这里非常有用)发布堆栈外观的摘录(递归部分)。添加了包含外部代码调用的Stacktrace。我不经常使用stacktrace,所以如果这些信息不是你想要的全部,请告诉我你想要什么。在抛出异常之前,我只是复制了VisualStudio跟踪中的所有内容。在异常发生后,VisualStudio说内存中保存的帧太多或类似的东西太多,并且没有可用的调用堆栈或反汇编。嗯。当您点击异常时,通常会出现一个对话框,比如“Break,Continue,Ignore”,您能点击Break并在那里看到完整的调用堆栈吗?它应该显示重复模式。另外,你能用LogsEnabled属性和它引用的私有变量发布app类的相关部分吗?看起来循环引用在那里,而不像我猜的那样位于DebugLevel属性中。添加了堆栈跟踪。因为LogsEnabled是一个clr属性,所以我必须在更新事件期间手动更新它的值,否则它就得不到更新的值。这是我知道的唯一一种方法,它不需要制作布尔变量的大量副本,也不需要为其分配logsEnabled的当前值。我认为绑定到app class属性可以节省重复的代码,但也许我错了。我倾向于在c#中使用这些类型的东西,因为我能够在vb中使用更多的东西。所以,如果我没有遵循好的设计模式,请务必让我知道我不会被冒犯。不,您在这里绑定应用程序类属性是正确的。我只是不确定我是否能在app类中找到这些信息。我个人会把它放在一个可供整个应用程序访问的静态对象中。总的来说,把东西放在应用程序类中让我觉得很奇怪。我通常只使用它来处理启动参数(在我编写既有UI又有命令行界面的应用程序的情况下)和实例化程序的主类