【问题标题】:How can I debug this StackOverflowException in my WinForm application?如何在我的 WinForm 应用程序中调试此 StackOverflowException?
【发布时间】:2011-08-30 09:57:12
【问题描述】:

我有一个 winform 应用程序。每隔几秒钟我就会检查一些日志文件,读入任何新数据并将任何新数据插入数据库。

当我运行应用程序大约一个小时 1/2 时,我得到一个 StackOverflowException。整个期间的日志文件中没有新数据,因此数据库中没有添加任何新数据。

这里的代码出错了……

if (pictureBox == null)
{
    continue;
}

if (pictureBox.InvokeRequired)
{
    var toolTip = new ToolTip();
    GameServer tempGameFile = gameServer;
    pictureBox.Invoke(new MethodInvoker(
        () => toolTip.SetToolTip(pictureBox,
            string.Format(
                "{0} : Last Checked: {1}; Last Updated: {2}",
                tempGameFile.Name,
                tempGameFile.CheckedOn.ToLongTimeString(),
                tempGameFile.UpdatedOn.HasValue
                    ?
                        tempGameFile.UpdatedOn.Value.ToLongTimeString()
                        : "-No Date Set-"))));
}
pictureBox.Image = Resources.RedButton;

pictureBox.Invoke(..) 正在抛出该错误。

所以 .. 我不知道如何才能弄清楚这是怎么回事?有什么建议吗?

更新

尝试Dmitry 的建议我已经启动了 ANTS 分析器内存配置文件 .. 并快速浏览了一些东西 .. 似乎有很多 ToolTip 控件的实例。

这是 20 分钟后的课程列表摘要。

很多事件处理程序(我没有发布什么吗?)

还有一些工具提示...

Here is a screenshot 的所有实例和 here is a screenshot 的单个 ToolTip 控制图/地图 .. 我不知道如何阅读 blush

【问题讨论】:

  • 是什么触发了发布的代码?它不包含方法签名并且不清楚,至少对我来说不是。
  • 这是我的问题 Samuel -> 我也不确定。这就是应用程序在pictureBox.Invoke(..) 方法上崩溃的地方。我不确定这是否是错误的,或者我如何确认?我想知道我是否一直在使用那条线调用但从不清理自己?否则我是否需要让其他应用程序来查看尚未清理的实例(仍然有对它们的恶意引用)或其他东西...... ???
  • 该代码放在哪个事件中?
  • 我已经让应用程序再次运行.. 需要再等一个小时左右才能抛出 SOE :( 现在.. 该代码放置在什么事件中?这是一个被调用的方法在GameServersParsingBackgroundWorker_DoWork .. 一个BackgroundWorker 进程内。
  • 很难想象这会给出一个 SO 错误。您的代码中是否有嵌套的事件处理程序和/或 Application.DoEvents()?错误出现在这里并不意味着它是在这里引起的。

标签: c# .net winforms debugging stack-overflow


【解决方案1】:

您的代码有 2 个潜在问题:

var toolTip = new ToolTip();

pictureBox.Image = Resources.RedButton;

都在非 UI 线程上调用。我必须使用Control.Invoke 将此代码marshal 发送到 UI 线程。如果解决这个问题没有帮助,请查看我在windows service 中关于如何调试 StackOverflowException 的回答。

更新:试试这个代码。请注意,每个引用任何 UI 控件的语句都需要使用 Control.Invoke 进行封送处理:

if (pictureBox == null || !pictureBox.IsHandleCreated) {
    continue;
}

Action setTooltipAndImage = () => {
    var toolTip = new ToolTip();
    GameServer tempGameFile = gameServer;
    toolTip.SetToolTip(pictureBox, string.Format(...));
    pictureBox.Image = Resources.RedButton;
};

if (pictureBox.InvokeRequired) {                        
    pictureBox.Invoke(setTooltipAndImage);
} else {
    setTooltipAndImage();
}

可能值得一读Manipulating Controls from Threads

【讨论】:

  • 所以我需要Invoke 这两个?现在我正在为SetToolTip 这样做......但这还不够吗?你能提供一些示例代码吗?我从后台线程访问这些 UI 元素是 100% 正确的。
  • 访问修改后的闭包:GameServer tempGameFile = gameServer; 所以我只是在Action setToolTipAndImage ... 代码上方制作了一个临时副本.. 即。 var tempGameServer = gameserver; Action setToolTipAndImage ... 另外,我的原始代码没有使用工具提示调用所有东西......所以我需要同时调用newSetToolTipResources.RedButton。明白了。
  • 我正在运行 ANTS 内存分析器并查看内存中 ToolTip 实例的存储桶负载。是否值得发布其中一个实例的图形/地图的图像.. 所以看看它在哪里处理?
  • @Pure.Krome:可能不值得动态创建尽可能多的工具提示而只重用一个实例。
  • kewl :) .. 但我不知道该怎么做。我希望 - 重用 - 现有的......并且只是“更新”它。
【解决方案2】:

如果您可以在调试模式下运行您的应用程序,当您遇到 StackOverflowException 并且应用程序进入 Visual Studio 时,请打开调用堆栈窗口(调试 -> Windows -> 调用堆栈)并查看是什么原因造成的你的代码抛出异常。

【讨论】:

    猜你喜欢
    • 2013-09-14
    • 2011-06-11
    • 2010-12-31
    • 2021-01-13
    • 1970-01-01
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多