简体   繁体   English

window.ShowDialog stackoverflowexception原因。 WPF

[英]window.ShowDialog stackoverflowexception reasons. WPF

What is main reasons for window.ShowDialog() stackOverflowException in WPF? WPF中window.ShowDialog()stackOverflowException的主要原因是什么? I receive this exception after 10-20 seconds when I call: 我拨打电话后10-20秒钟收到此异常:

if(myWindow.ShowDialog() == true)
{
   //other stuff
}

Window is shows up and works good, but then I receive this exception. 窗口显示并运行良好,但后来我收到此异常。

The generic cause of an SOE like this is having an event handler whose code causes the same event to be raised again. 像这样的SOE的一般原因是有一个事件处理程序,其代码导致再次引发相同的事件。 A simple example is: 一个简单的例子是:

    private void textBox1_TextChanged(object sender, TextChangedEventArgs e) {
        textBox1.Text += "a";
    }

Type a letter, takes about 5 seconds for program to run out of stack space and bomb. 键入一个字母,大约需要5秒钟,以便程序耗尽堆栈空间和炸弹。 Your primary weapon to diagnose exactly which event handler causes this problem is the debugger, look at the Call Stack window. 准确诊断哪个事件处理程序导致此问题的主要武器是调试器,请查看“调用堆栈”窗口。 You solve it by using a little helper variable that indicates that you expect the event to be fired again so you can ignore it. 您可以通过使用一个小辅助变量来解决它,该变量指示您希望再次触发事件,以便您可以忽略它。 Like this: 像这样:

    bool changingText;

    private void textBox1_TextChanged(object sender, TextChangedEventArgs e) {
        if (changingText) return;
        changingText = true;
        try {
            textBox1.Text += "a";
        }
        finally {
            changingText = false;
        }
    }

The try/finally is not strictly necessary but wise if you expect to keep your program running after an exception. try / finally并不是绝对必要的,但如果你希望在异常之后保持你的程序运行,这是明智的。

Surprisingly a stack overflow exception can be caused by repeatedly calling window.ShowDialog asynchronously. 令人惊讶的是,异步重复调用window.ShowDialog可能导致堆栈溢出异常。

    public MainWindow()
    {
        InitializeComponent();
        TheCallDelegate = TheCall;
        _timer = new DispatcherTimer();
        _timer.Tick += _timer_Tick;
        _timer.Start();
    }

    DispatcherTimer _timer = null;

    void _timer_Tick(object sender, EventArgs e)
    {
        _timer.Dispatcher.BeginInvoke(TheCallDelegate);            
    }

    Action TheCallDelegate;

    void TheCall()
    {
        Window win = new Window();
        win.ShowDialog();
    }

As you can see there is no actual recursion here (or there shouldn't have been) but once the exception happens you can see that the call stack is indeed full. 正如您所看到的,这里没有实际的递归(或者应该没有)但是一旦发生异常,您就可以看到调用堆栈确实已满。 Without looking at how Window.ShowDialog is implemented internally I can't say what is the deeper cause of this. 没有看看Window.ShowDialog是如何在内部实现的,我不能说这是什么原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM