时间:2019-03-27 标签:c#settings+堆栈溢出异常
我的 wpf 应用程序中有一个用户控件,当多次实例化它时,会导致 stackoverflowException 被捕获。我尝试调试异常的原因,它是在我的用户控件的 InitializeComponent 期间引发的。当我输入 InitializeComponent 时,它会跳转到 app.xaml.cs 代码隐藏并读取 Settings 类中包含的值。
我是使用 C# 应用程序设置的“新手”,因此之前没有遇到过此错误。不确定在与他们合作时这是否常见。此外,这是我的应用程序中当前唯一允许修改设置变量的用户控件,也是唯一表现出此行为的用户控件。
我认为我的问题与使用“Application.Current”数据上下文的 DebugOptions 类有关,然后我使用相同的数据上下文创建另一个实例,但一旦我访问它的任何属性,我就会让应用程序对哪个 obj 感到困惑哪个。虽然这在我看来是有道理的,但从逻辑上讲,它并不是这样工作的,因为该用户控件是在单击按钮时实例化的,并且在添加之前会清除其主机面板以防止多个实例滚动。
下面发布的是我的用户控件的 xaml 和代码隐藏。除了它绑定到的 App 类的 CLR 属性之外,它没有任何依赖项。我希望我能提供更多关于此的信息,但这是一个非常奇怪的例外情况。
这是我的 App 类中的属性,在“获取”访问时会导致 stackoverflow 异常。
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);
}
}
为简洁起见,省略了用户控件资源和用户控件标签在
<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>
抛出异常之前的堆栈跟踪
Merlin.exe!Merlin.App.LogsEnabled.set(bool value = 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(object sender = {Merlin.ImageButton}, System.Windows.RoulatedEventArgs e = {System.Windows.RoulatedEventArgs}) 第 218 行 + 0x15 字节 C# [外部代码]
奇怪的是,在初始化组件例程期间,获取了“LogsEnabled”布尔值,然后立即调用来设置它。我不知道什么叫它来设置它。但一旦它设置了该值,它就会尝试再次获取该值。我确信运行时会引发堆栈溢出以防止无限循环。那么我怎样才能弄清楚它为什么要这样做呢?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
堆栈溢出可能是循环定义引用的结果:看起来可能发生这种情况的一种方式是滑块控件绑定到 DebugLevel。但是,当您输入 update 方法时,它将 DebugLevel 的值定义为滑块控件的值。
所以你可能会得到这样的信息:
滑块控件的值?哦 - 我会去查找 DebugLevel。
调试级别的值?哦,我去查一下滑块控件的值。
滑块控件的值?哦 - 我会去查找 DebugLevel。
我不确定,但这可能是问题所在。
(就像上面提到的评论者提到的那样,堆栈跟踪在这里非常有帮助)
The stack overflow is probably as a result of a circularly-defined reference: it looks like one way this might happen is that your slider control is bound to DebugLevel. However, when you enter the update method, it defines the value of the DebugLevel to that of the slider control.
So you might get something like:
Slider control's value? Oh - I'll go look up DebugLevel.
DebugLevel's value? Oh, I'll go look up slider control's value.
Slider control's value? Oh - I'll go look up DebugLevel.
I'm not certain, but that could be the problem.
(like the above commenter mentioned, a stack trace would be really helpful here)