System.StackOverflowException WPF MVVM

本文关键字:MVVM WPF StackOverflowException System | 更新日期: 2023-09-27 17:51:13

我正在尝试使用MVVM在WPF中创建一个简单的数字时钟。我有一个有绑定的标签。背后的代码很简单,每秒引发一个属性改变事件,我有一个stackoverflow异常。有人能帮帮忙吗?

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
    }
    private string _lblValue;
    public string LabelValue
    {
        get
        {
            UpdateLabel();
            return _lblValue;
        }
        set
        {
            _lblValue = value;
            OnPropertyChanged(LabelValue);
        }
    }
    private void UpdateLabel()
    {
        _lblValue = System.DateTime.Now.ToString();
        //System.Threading.Thread.Sleep(2000);
        OnPropertyChanged("LabelValue");
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propName)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propName));
        }
    }
}

System.StackOverflowException WPF MVVM

正如har07解释的那样,这是一个无限UI循环。这是我对这个问题的解决方案。

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
        Task.Run(() => UpdateLabel());
    }
    private string _lblValue;
    public string LabelValue
    {
        get
        {
            return _lblValue;
        }
        set
        {
            _lblValue = value;
            OnPropertyChanged();
        }
    }
    private void UpdateLabel()
    {
        while (true)
        {
            LabelValue = System.DateTime.Now.ToString();
            System.Threading.Thread.Sleep(1000);
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propName = null)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propName));
        }
    }
}

结果如下:

  1. LabelValue
  2. getter中调用的UpdateLabel()函数
  3. UpdateLabel() call OnPropertyChanged("LabelValue");
  4. 步骤2导致UI检查属性LabelValue的更新值;换句话说,它导致LabelValue的getter名为
  5. 返回步骤1
以上所有步骤重复,直到抛出stackoverflow异常。尝试删除步骤2来解决问题。

在您的情况下,最好使用间隔为1秒的计时器。
例如:

using System.Timers;

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private Timer _clockTimer;
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
       _clockTimer = new Timer(1000); // The interval is in milliseconds
       _clockTimer.Elapsed += (sender, e) =>
       {
           LabelValue = System.DateTime.Now.ToString();
       };
    }
    private string _lblValue;
    public string LabelValue
    {
        get
        {
            return _lblValue;
        }
        set
        {
            _lblValue = value;
            OnPropertyChanged("LabelValue");
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propName)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propName));
        }
    }
}


如果你对计时器有更多的问题,你可以在MSDN上查看更多信息。