我正在使用DataGridView
控件,我将下面的处理程序添加到DataGridView.CellFormatting
事件中,因此可以使某些单元格中的值更具人性化。这个事件处理程序工作得很好,格式化所有值没有问题。
最近,我发现一种非常罕见的情况会导致一个不寻常的错误。我DataGridView
中该项目截止日期的列始终具有int
值。 0
表示事件永远不会到期,任何其他值都是截止日期的UTC时间戳。相应的MySQL db列不允许空值。当用户从具有截止日期的DataGridView
行移动到具有截止日期的另一DataGridView
行时(此时一切仍然显示正常),然后按下重新加载数据的按钮从数据库(不发送更新,基本上调用DataAdapter.Fill()
),程序生成StackOverflowException
**。
对我来说不寻常的是我没有看到递归或infinte-looping的位置。我添加int cellFormatCallCount
作为类成员,并在每次调用期间递增它,但是在抛出异常时,调试器将该int
的值显示为1,这是我所期望的,因为我没有在印象和递归之下。
有人能帮助我吗?
如何查看堆栈跟踪?在VS2008中它说:
{Cannot evaluate expression because the current thread is in a stack overflow state.}
致以最诚挚的问候,
罗宾逊
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
}
}
答案 0 :(得分:5)
显然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--;
...
}
答案 1 :(得分:2)
完全随机猜测(没有堆栈跟踪,这是我能做的全部)......
您是否尝试显示/格式化具有潜在递归的类型ToString()
?
public string ToString()
{
return ... this.ToString() ...
// or
return String.Format("The value is {0}", this);
}
这样的拼写错误/错误可能导致StackOverflowException
...
答案 2 :(得分:1)
@Daniel:如果那是问题,那么它不会在行中引发异常:
if (e.Value != null) {
@gnirts:你也可以发布完整的方法和堆栈跟踪吗?
@BCS(下面):我认为可能是这样,但它可能很容易出现在deo发布的一些代码中。
PS。对不起,这应该是评论,但我没有足够的代表:-D
答案 3 :(得分:1)
鉴于这是一个事件,它可能会引发它的自我吗?
答案 4 :(得分:1)
尝试将cellFormatCallCount变量设为静态,以便它由该类的所有实例共享。我怀疑事件是以某种方式触发它自己但你没有看到它,因为cellFormatCallCount只对处理事件的类的每个实例都是本地的,因此永远不会超过1.如果是这种情况,那么stackoverflow的实际触发器(递归)可以在方法中的任何地方,它恰好在该行的堆栈空间用完。
一旦你将变量设为静态,你就可以在超过某个(小)值时抛出异常,例如2.该异常应该留下可见的堆栈跟踪。
答案 5 :(得分:0)
这与问题无关,但你实际上只有StackOverflowException
没有递归而只有:
throw new StackOverflowException();
答案 6 :(得分:0)
我刚遇到类似stackoverflow的问题而没有跟踪细节。
我的问题是由于一个不应该实例化的对象实例。我删除了违规的新对象,一切都很好。
在上述情况下,如果没有看到更多代码,请确保不使用= - 触发多个事件来相应地取消事件。
我希望这可以帮助别人。