C#中从抛出方法中获取方法参数
我有一个令人讨厌的异常,似乎发生在 DataGridView 代码深处。
我有一个继承自 BindingList 的类,它是 BindingSource 的 DataSource,而 BindingSource 是 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),如下所示: 有人编写过线程安全的 BindingList
I have a nasty exception that seems to occure deep inside the DataGridView Code.
I have a class that inherits from BindingList which is the DataSource of a BindingSource which is the DataSoure of a DataGridView.
Under some strange circumstances I get an exception during the overridden OnListChanged() method of my class:
protected override void OnListChanged(ListChangedEventArgs e)
{
base.OnListChanged(e); // <-- ArgumentOutOfRangeException
// ...Parametername: rowIndex
}
the stacktrace looks like this:
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)
Well, I could just add a try\catch exception around this, but I am curious why this happens at all.
Someone told me one time, I could use the mighty power of reflections and System.Diagnostics.StackTrace to get the StackFrame which causes the exception
(That works so far) and inspect the parameters (I have no clue how to do this) which would help me, beause if I know the value from rowindex / columnindex I could track down the exception.
Can anybody tell me, if possible at all, to get the Parameters from the Exception?
Thanks in advance!
Update:
The problem seems to be related to some threading issues and has nothing to do with the rowIndex.
BindingList is the datasource of an DataGridView. If I add an Element to the list the OnListChanged event fires, which causes the dataGridView to load the databound properties from the new instance of T.
In the getter of one property I had some code that changed another property which caused the OnPropertyChanged Event of the T instace to be fired.
Just one simple lock(this) in the BindingList Add method like here:
Has anyone written a thread-safe BindingList<T>?
solved the problem for me. Hard to debug ;(
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
乍一看(以及第二次和第三次),卢克是对的,但看得更远可能有办法。通过 StackTrace 类直接使用方法的问题是行不通的,因为该类存储堆栈信息,包括参数信息,但不存储参数数据。
此数据将在调试版本中提供,而不是在发布版本中提供。要获取该数据,您可以与 Visual Studio 的调试器进行交互。您可以通过编程方式执行此操作。但是,我认为调用 Debugger.Break() 更容易(并且可能首先检查是否附加了调试器),然后进行分析。
要与 IDE 和调试器交互,这里有一个答案解释how(它解释了如何以编程方式设置断点,但通过与 IDE 交互来实现)。
要查找所需信息,您可以使用在 IDE 中编写宏时可用的自动化方法。如果您能够反映堆上对象的方式,那就更容易了,而且可能有一个,但这是迄今为止我能找到的唯一可行的方法。
At first sight (and second and third sight), Luke is right, but looking further there might be a way. The problem using a straight approach through the StackTrace class doesn't work, simply because that class stores the stack information, including the parameter info, but not the parameter data.
This data would be available in a debugging version, not in a release version. To get to that data, you can interact with the debugger of visual studio. You can do so programmatically. However, I think it is easier to call
Debugger.Break()
(and possibly checking whether there's a debugger attached first) and then do the analysis.To interact with the IDE and the debugger, here's an answer that explains how (it explains how to set breakpoints programmatically but does so by interacting with the IDE).
To find the information you're after, you can use the automation methods that would be available when you're in the IDE writing a macro. It would be easier if you could reflect your way to the objects on the heap, and possibly there is one, but this is the only workable method I could find so far.
不幸的是,您无法从堆栈跟踪或异常中获取参数值。
ListChangedEventArgs
可能有助于调试的参数:ListChangedType
,NewIndex
、OldIndex
和PropertyDescriptor
。Unfortunately you can't get the argument values from the stacktrace or exception.
There are various properties available on the
ListChangedEventArgs
parameter that might help with debugging:ListChangedType
,NewIndex
,OldIndex
andPropertyDescriptor
.