【问题标题】:Get the method parameters from the throwing method in C#从 C# 中的 throwing 方法中获取方法参数
【发布时间】:2010-12-23 04:25:14
【问题描述】:

我有一个令人讨厌的异常,似乎发生在 DataGridView 代码的深处。

我有一个继承自 BindingList 的类,它是 BindingSource 的 DataSource,它是 DataGridView 的 DataSoure。

在某些奇怪的情况下,我在类的重写 OnListChanged() 方法期间遇到异常:

    protected override void OnListChanged(ListChangedEventArgs e)
    {
        base.OnListChanged(e); // <-- ArgumentOutOfRangeException
                               // ...Parametername: rowIndex
    }

堆栈跟踪如下所示:

    bei System.Windows.Forms.DataGridView.GetCellDisplayRectangle(Int32 columnIndex, Int32 rowIndex, Boolean cutOverflow)
    bei System.Windows.Forms.DataGridView.GetCellAdjustedDisplayRectangle(Int32 columnIndex, Int32 rowIndex, Boolean cutOverflow)
    bei System.Windows.Forms.DataGridView.InvalidateCellPrivate(Int32 columnIndex, Int32 rowIndex)
    bei System.Windows.Forms.DataGridView.OnCellCommonChange(Int32 columnIndex, Int32 rowIndex)
    bei System.Windows.Forms.DataGridView.DataGridViewDataConnection.ProcessListChanged(ListChangedEventArgs e)
    bei System.Windows.Forms.DataGridView.DataGridViewDataConnection.currencyManager_ListChanged(Object sender, ListChangedEventArgs e)
    bei System.Windows.Forms.CurrencyManager.OnListChanged(ListChangedEventArgs e)
    bei System.Windows.Forms.CurrencyManager.List_ListChanged(Object sender, ListChangedEventArgs e)
    bei System.Windows.Forms.BindingSource.OnListChanged(ListChangedEventArgs e)
    bei System.Windows.Forms.BindingSource.InnerList_ListChanged(Object sender, ListChangedEventArgs e)
    bei System.ComponentModel.ListChangedEventHandler.Invoke(Object sender, ListChangedEventArgs e)
    bei System.ComponentModel.BindingList`1.OnListChanged(ListChangedEventArgs e)
    bei My.Own.BindingList.OnListChanged(ListChangedEventArgs e)

好吧,我可以添加一个 try\catch 异常,但我很好奇为什么会发生这种情况。

曾经有人告诉我,我可以使用反射和 System.Diagnostics.StackTrace 的强大功能来获取导致异常的 StackFrame (到目前为止有效)并检查对我有帮助的参数(我不知道该怎么做),因为如果我知道 rowindex / columnindex 的值,我可以追踪异常。

如果可能的话,谁能告诉我从异常中获取参数?

提前致谢!

更新:

该问题似乎与某些线程问题有关,与 rowIndex 无关。 BindingList 是 DataGridView 的数据源。如果我将一个元素添加到列表中,则会触发 OnListChanged 事件,这会导致 dataGridView 从 T 的新实例加载数据绑定属性。 在一个属性的 getter 中,我有一些代码更改了另一个属性,导致 T 实例的 OnPropertyChanged 事件被触发。

BindingList Add 方法中只有一个简单的锁(this),如下所示: Has anyone written a thread-safe BindingList<T>? 为我解决了这个问题。难以调试;(

【问题讨论】:

  • 是的,线程问题很难调试。很高兴你找到它!

标签: c# .net exception datagridview stack-trace


【解决方案1】:

第一眼(以及第二眼和第三眼),卢克是对的,但进一步观察可能会有办法。通过 StackTrace 类使用直接方法的问题不起作用,因为该类存储堆栈信息,包括参数信息,但不存储参数数据。

此数据在调试版本中可用,而不是在发布版本中。要获取该数据,您可以与 Visual Studio 的调试器进行交互。您可以以编程方式执行此操作。但是,我认为调用Debugger.Break() (并可能先检查是否附加了调试器)然后进行分析更容易。

要与 IDE 和调试器交互,here's an answer that explains how(它解释了如何以编程方式设置断点,但通过与 IDE 交互来实现)。

要查找所需的信息,您可以使用在 IDE 中编写宏时可用的自动化方法。如果您可以将自己的方式反映到堆上的对象会更容易,并且可能有一个,但这是迄今为止我能找到的唯一可行的方法。

【讨论】:

  • 我可以在我的 Visual Studio IDE 中重现此错误。问题是 DataGridView 似乎“监听”了 BindingList ListChanged 事件,并在我的属性“Prop1”更改时导致异常发生。 Prop1 在网格中有 rowId 3,所以我很好奇为什么我得到 ArgumentOutOfRangeException 并想知道堆栈顶部的方法 GetCellDisplayRectangle(...) 中 rowId 的值是什么。
  • 如果在调试过程中遇到异常,打开调用堆栈窗口,双击堆栈中带有GetCellDisplayRectangle()的行。将鼠标悬停在该函数中的变量或参数rowId 上,您将能够看到它的值。或者,您可以创建一个条件断点在发生异常之前,以中断rowId==3 上的该函数。为此,请创建一个断点GetCellDisplayRectangle,右键单击它,选择“条件”并在“条件”对话框中键入“rowId==3”。正如我的答案中的链接所示,自动化任一过程都是可能的,但很难。
【解决方案2】:

很遗憾,您无法从堆栈跟踪或异常中获取参数值。

ListChangedEventArgs 参数上有各种可能有助于调试的属性:ListChangedTypeNewIndexOldIndexPropertyDescriptor

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多