Настройки c # + StackOverflowException - PullRequest
       5

Настройки c # + StackOverflowException

1 голос
/ 20 октября 2010

В моем приложении wpf есть usercontrol, который вызывает исключение stackoverflow, когда оно создается более одного раза. Я попытался отладить причину исключения, и оно возникло во время InitializeComponent моего Usercontrol. Когда я вхожу в InitializeComponent, он переходит на код приложения app.xaml.cs и считывает значения, содержащиеся в классе «Настройки».

Я "новичок" в использовании настроек приложения C #, поэтому раньше я не сталкивался с этой ошибкой. Не уверен, является ли это обычным делом или нет при работе с ними. Кроме того, это единственный пользовательский контроль в настоящее время в моем приложении, который позволяет изменять переменные настроек, и это единственный пользовательский контроль, который демонстрирует такое поведение.

Я думаю, что моя проблема как-то связана с классом DebugOptions, использующим текст данных «Application.Current», и затем я создаю другой экземпляр с тем же текстом данных, но как только я получаю доступ к любому из его свойств, я начинаю путать приложение какой объект есть какой. Хотя это имеет смысл в моей голове, логически это не сработает, потому что этот пользовательский контроль запускается при нажатии кнопки, а его панель хоста очищается перед добавлением, чтобы предотвратить вращение нескольких экземпляров.

Ниже приведены xaml и код моего управления пользователями. Он не имеет зависимостей, кроме свойств CLR из класса App, с которым он связан. Я бы хотел, чтобы у меня было больше информации по этому вопросу, но это очень странное исключение, которое появляется.

Вот свойство в моем классе приложения, которое вызывает исключение stackoverflow при обращении к нему «Get».

 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 (значение bool = 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.RoutedEventArgs e = {System.Windows.RoutedEventArgs}) Строка 218 + 0x15 байт C # [Внешний код]

Странно, что во время процедуры initializecomponent получается логическое значение LogsEnabled, а затем сразу же вызывается для его установки. Я понятия не имею, что вызывает это, чтобы установить это. Но как только он устанавливает значение, он пытается получить его снова. Я уверен, что среда выполнения выбрасывает стековый поток, чтобы предотвратить бесконечный цикл. Так как я могу понять, почему он хочет это сделать?

1 Ответ

2 голосов
/ 21 октября 2010

Переполнение стека, вероятно, является результатом циклически заданной ссылки: похоже, что единственный способ, которым это может произойти, это то, что ваш элемент управления ползунком связан с DebugLevel. Однако, когда вы вводите метод обновления, он определяет значение DebugLevel, равное значению элемента управления ползунка.

Так что вы можете получить что-то вроде:

Значение ползункового элемента управления? Ох, я пойду посмотрю DebugLevel. Значение DebugLevel? О, я пойду посмотрю значение элемента управления ползунком. Значение ползункового элемента управления? Ох, я пойду посмотрю DebugLevel.

Я не уверен, но это может быть проблемой.

(как упоминалось выше, упомянутый выше комментатор, трассировка стека была бы очень полезна здесь)

...