时间:2019-03-27 标签:c#settings+堆栈溢出异常

发布于 2024-09-28 01:20:11 字数 7001 浏览 5 评论 0 原文

我的 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”布尔值,然后立即调用来设置它。我不知道什么叫它来设置它。但一旦它设置了该值,它就会尝试再次获取该值。我确信运行时会引发堆栈溢出以防止无限循环。那么我怎样才能弄清楚它为什么要这样做呢?

I have a usercontrol in my wpf application which is causing a stackoverflowexception to be caught when it is instanced more than once. I tried to debug the cause of the exception and it is raised during InitializeComponent of my Usercontrol. When I enter InitializeComponent it jumps over to the app.xaml.cs codebehind and reads values which are contained in the Settings class.

I am "new" to using C# application settings so I have not experienced this error before. Not sure if this is commonplace or not when working with them. Also, this is the only usercontrol currently in my app that allows modification of the settings variables and it is the only usercontrol which exhibits this behavior.

I think my problem has something to do with the DebugOptions class using a datacontext of "Application.Current" and then I create another instance with that same datacontext but as soon as I access any of its properties I get the application confused about which obj is which. While that makes sense in my head, logically it doesn't work out that way because this usercontrol is instanced upon a button click and it's host panel is cleared before adding to prevent multiple instances from rolling around.

Posted below is the xaml and codebehind of my usercontrol. It has no dependencies except for the CLR properties from the App class that it binds to. I wish I had more info to provide on this but it's a very odd exception that creeps up.

Here is the property in my App class which causes the stackoverflow exception when it is "Get" accessed.

 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 resources and UserControl tags omitted for brevity

<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 BEFORE exception thrown

Merlin.exe!Merlin.App.LogsEnabled.set(bool value = false) Line 52 C#
[External Code]
Merlin.exe!Merlin.View.DebugOptions.DebugOptions() Line 25 + 0x8 bytes C#
[External Code]
Merlin.exe!Merlin.View.TestView.TestView() Line 24 + 0x8 bytes C#
Merlin.exe!Merlin.MainWindow.SidebarButtonsClickHandler(object sender = {Merlin.ImageButton}, System.Windows.RoutedEventArgs e = {System.Windows.RoutedEventArgs}) Line 218 + 0x15 bytes C#
[External Code]

What's odd is that during the initializecomponent routine the "LogsEnabled" boolean value is gotten and then immediately it calls to set it. I have no idea what's calling it to set it. But as soon as it sets the value it tries to get it again. I'm sure the runtime is throwing the stackoverflow to prevent an infinite loop. So how can I figure out why it wants to do this?

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

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

发布评论

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

评论(1

£冰雨忧蓝° 2024-10-05 01:20:11

堆栈溢出可能是循环定义引用的结果:看起来可能发生这种情况的一种方式是滑块控件绑定到 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)

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