C# 没有递归或无限循环的StackOverflowException? 背景

C# 没有递归或无限循环的StackOverflowException? 背景,c#,datagridview,recursion,stack-overflow,C#,Datagridview,Recursion,Stack Overflow,我正在使用一个DataGridView控件,我将下面的处理程序添加到DataGridView.CellFormatting事件中,以便使某些单元格中的值更易于阅读。这个事件处理程序工作得很好,格式化所有值都没有问题 然而,最近我发现了一个非常罕见的情况导致了一个不寻常的错误。myDataGridView中项目到期日的列始终具有int值0表示事件从未到期,任何其他值都是到期日期的UTC时间戳。对应的MySQL db列不允许空值。当用户从一个带有到期日期的DataGridView行移动到另一个带有到

我正在使用一个
DataGridView
控件,我将下面的处理程序添加到
DataGridView.CellFormatting
事件中,以便使某些单元格中的值更易于阅读。这个事件处理程序工作得很好,格式化所有值都没有问题

然而,最近我发现了一个非常罕见的情况导致了一个不寻常的错误。my
DataGridView
中项目到期日的列始终具有
int
值<代码>0表示事件从未到期,任何其他值都是到期日期的UTC时间戳。对应的MySQL db列不允许空值。当用户从一个带有到期日期的
DataGridView
行移动到另一个带有到期日期的
DataGridView
行时(此时一切仍然正常),然后按下按钮从数据库重新加载数据(不发送更新,基本上调用
DataAdapter.Fill()
),程序生成一个
StackOverflowException
**

没有递归? 对我来说非常不寻常的是,我看不到递归或infinte循环在哪里。我添加了
int-cellFormatCallCount
作为类成员,并在每次调用期间递增它,但在抛出异常时,调试器将该
int
的值显示为1,这是我所期望的,因为我没有感觉到,递归正在发生

有人能帮我吗

如何查看堆栈跟踪?在VS2008中,它说:
{无法计算表达式,因为当前线程处于堆栈溢出状态。}

致以最良好的祝愿

罗宾逊

private int cellFormatCallCount = 0;
private void myDataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)  {
    try {
        // to format the cell, we will need to know its value and which column its in
        string value = "";
        string column = "";
        
        // the event is sometimes called where the value property is null
        if (e.Value != null) {
            cellFormatCallCount++; // here is my test for recursion, this class member will increment each call

            // This is the line that throws the StackOverflowException
            /* ********************* */
            value = e.Value.ToString();
            /* ********************* */

            column = actionsDataGridView.Columns[e.ColumnIndex].Name;
        } else {
            return; // null values cannont be formatted, so return
        }

        if (column == "id") {
            // different code for formatting each column
        } else if (column == "title") {
            // ...
        } else {
            // ...
        }
    } finally {
        cellFormatCallCount = 0; // after we are done with the formatting, reset our recursion counter
    }
}
完全随机猜测(没有堆栈跟踪,这是我所能做的一切)

您是否试图显示/格式化具有潜在递归的
ToString()
的类型


这样的键入/错误可能会导致
StackOverflowException

这与问题无关,但实际上,您可以使用
StackOverflowException
而无需递归,只要:

throw new StackOverflowException();

@丹尼尔:如果这就是问题所在,那么它是否已经在队列中引发了异常:

if (e.Value != null) {
@gnirts:你能发布完整的方法和堆栈跟踪吗

@BCS(如下):我认为可能是这样,但它可能很容易出现在deo发布的部分代码中


PS.对不起,这应该是一个注释,但我没有足够的重复:-D

鉴于这是一个事件,它是否会触发自身?

尝试将cellFormatCallCount变量设置为静态,以便该类的所有实例都共享它。我怀疑事件是以某种方式触发自身的,但您没有看到它,因为cellFormatCallCount只是处理事件的类的每个实例的本地实例,因此其增量永远不会超过1。如果是这种情况,那么stackoverflow(递归)的实际触发器可能在方法中的任何位置,并且恰好在该行耗尽堆栈空间


一旦将变量设置为静态,当它超过某个(小)值时,可以抛出异常,如2。该异常应留下一个可查看的堆栈跟踪。

显然,e.Value.ToString()再次调用CellFormatting事件。这似乎有点合乎逻辑。使用调试器应该很容易找到

但是实际的递归可能是在其他地方引起的,比如在您忽略的每列格式中

您的递归检查不可靠,因为Value==null也将重置它,并且它似乎由所有列共享。使其更紧密地围绕e.Value.ToString():

if (e.Value != null) 
{
   cellFormatCallCount++; 
   System.Diagnostics.Debug.Assert(cellFormatCallCount <= 1, "Recursion");
   value = e.Value.ToString();
   cellFormatCallCount--; 
   ...
} 
if(e.Value!=null)
{
cellFormatCallCount++;

System.Diagnostics.Debug.Assert(cellFormatCallCount我刚刚遇到了类似的stackoverflow问题,没有跟踪细节

我的问题是由于一个不应该被实例化的对象的实例。我删除了有问题的新对象,一切都很好

在上面的情况下,如果看不到任何代码,请确保没有使用=-触发多个事件以相应地取消事件


我希望这可能会对某人有所帮助。

你能发布堆栈跟踪吗?那会很有帮助。我以为这条帖子是关于这个网站的。天哪,我需要休息一下=p@JoshJordan-我也是!我想知道他是怎么从网站上得到一个异常的。嘘!如果你在违规的线路上设置一个断点,你能进入e.V.的财产访问权限吗Value?你能快速查看e.Value吗?如果可以,你看到了什么?这是一个很长的过程,但是e.Value中有什么?如果递归定义了ToString,那么你可能会有一个stackoverflow。是的,这听起来很疯狂,但比你想象的要容易,特别是当你有一个具有允许你进行“设置”的属性的对象时使用可能恰好包含自身的类型对象。请参阅:如果希望看到堆栈溢出,则需要将断点放在发生溢出的位置,而不是放在异常上。我会尝试将其放在它所表示的位置,并尝试查看它从何处开始。不,我没有将DataGridViewCellFormattingEventArgs子类化。@gnirts:如果您在导致SO的行上设置了一个(可能是有条件的)断点,您应该能够进入它…这可以帮助您识别递归路径…您可以通过放置一个等效的e.Value.ToString()来测试ToString()方法的负值在方法前面,看看是否有stackoverflow…如果没有,它不可能是ToString。如果.net提供的DataGridViewCellFormattingEventArgs类以这种方式实现ToString,我认为这并不奇怪:)请参阅:-)这将有一个堆栈跟踪。真正的堆栈溢出不允许您计算任何内容。@Darren Kopp:“真正的”堆栈溢出使您能够询问、回答和评论问题:)我向类成员添加了静态修饰符,但当时计数仍然是1
if (e.Value != null) 
{
   cellFormatCallCount++; 
   System.Diagnostics.Debug.Assert(cellFormatCallCount <= 1, "Recursion");
   value = e.Value.ToString();
   cellFormatCallCount--; 
   ...
}