This is an odd one. I have a DataGridView
. I'm setting its DataSource
with a List
containing objects of my own custom class. There are about 50,000 items in the list. I defined all of the columns I wanted to be visible in the Designer and set AutoGenerateColumns
to false.
As soon as I set the DataSource
to my list, it is immediately populated correctly. I can scroll up and down, select different rows. Everything is good. But when I scroll all of the way down and then let the window containing the DataGridView
lose focus everything freezes up and after a short while the stack overflows as such:
System.Drawing.dll!System.Drawing.SafeNativeMethods.Gdip.GdipDeleteGraphics(System.Runtime.InteropServices.HandleRef graphics) + 0x2a bytes
System.Drawing.dll!System.Drawing.Graphics.Dispose(bool disposing) + 0x56 bytes
System.Drawing.dll!System.Drawing.Graphics.Dispose() + 0x12 bytes
System.Drawing.dll!System.Drawing.Font.GetHeight() + 0xc8 bytes
System.Drawing.dll!System.Drawing.Font.Height.get() + 0xb bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.DataGridViewRow() + 0x44 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.Clone() + 0x44 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRowCollection.this[int].get(int index) + 0xa8 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.DataGridViewAccessibleObject.GetChild(int index) + 0xbd bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get() + 0x76 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get() + 0x83 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get() + 0x83 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get() + 0x83 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get() + 0x83 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get() + 0x83 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get() + 0x83 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get() + 0x83 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get() + 0x83 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get() + 0x83 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get() + 0x83 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get() + 0x83 bytes
...
For some reason the DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get()
method is calling itself into oblivion. The whole stack seems rather strange to me. Why would Font.Height.get()
ever call the DataGridViewRow
?
EDIT:
I was asked for some code. This is the designer generated code for the DataGridView
and its columns:
//
// dataGridView
//
this.dataGridView.AllowUserToAddRows = false;
this.dataGridView.AllowUserToDeleteRows = false;
this.dataGridView.AllowUserToOrderColumns = true;
this.dataGridView.AllowUserToResizeRows = false;
this.dataGridView.BackgroundColor = System.Drawing.SystemColors.Window;
this.dataGridView.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Date,
this.Type,
this.Job,
this.Mix,
this.Entry});
this.dataGridView.Location = new System.Drawing.Point(8, 96);
this.dataGridView.Name = "dataGridView";
this.dataGridView.ReadOnly = true;
this.dataGridView.RowHeadersVisible = false;
this.dataGridView.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dataGridView.Size = new System.Drawing.Size(1152, 504);
this.dataGridView.TabIndex = 10;
this.dataGridView.SelectionChanged += new System.EventHandler(this.dataGridView_SelectionChanged);
//
// Date
//
this.Date.DataPropertyName = "FormattedTime";
this.Date.HeaderText = "Date/Time";
this.Date.Name = "Date";
this.Date.ReadOnly = true;
//
// Type
//
this.Type.DataPropertyName = "FormattedType";
this.Type.FillWeight = 60F;
this.Type.HeaderText = "Type";
this.Type.Name = "Type";
this.Type.ReadOnly = true;
this.Type.Width = 60;
//
// Job
//
this.Job.DataPropertyName = "Job";
this.Job.FillWeight = 80F;
this.Job.HeaderText = "Job No.";
this.Job.Name = "Job";
this.Job.ReadOnly = true;
this.Job.Width = 80;
//
// Mix
//
this.Mix.DataPropertyName = "Mix";
this.Mix.FillWeight = 80F;
this.Mix.HeaderText = "Mix No.";
this.Mix.Name = "Mix";
this.Mix.ReadOnly = true;
this.Mix.Width = 80;
//
// Entry
//
this.Entry.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
this.Entry.DataPropertyName = "FormattedSummary";
this.Entry.HeaderText = "Entry";
this.Entry.Name = "Entry";
this.Entry.ReadOnly = true;
When time comes around to populate the grid view, I simply do a:
dataGridView.DataSource = myList;
Fix
No fix is known at this time.
Workaround
Disabling the Tablet PC Input Service (a.k.a. tabtip.exe) from the Services panel in Control Panel.
Details
A few weeks ago I contacted Microsoft Developer support about this issue. I corresponded with a support engineer on the WinForms team and we figured out that this issue was in some way caused by Accessibility.dll being loaded into my application whenever Microsoft's Tablet PC Input Service (tabtip.exe) was running. This service is present on at least all Windows 7 Enterprise installations but is generally only running if you have a tablet PC or have ever installed any sort of pen input device on your PC. I had used a Wacom Bamboo pen tablet on my PC in the past so it made sense why this service was running. Note that it was determined that neither the method I used to populate the DataGridView
nor any of the properties I set had anything to do with the issue.
Accessibility.dll is a Microsoft library that allows certain peripherals (pen tablets and especially assistive devices) to more easily interact and get extra information about forms and the controls contained on forms. I'm not 100% sure on this but I believe that this library is loaded into every running Windows process automatically if such a peripheral is installed.
After examining a dump that I had provided, the Microsoft engineer was puzzled by the code path that the DataGridView
decided to go down and found that Accessibility.dll was the culprit that allowed let it happen. He admitted that DataGridView
should not be doing this and that this seemed like a problem on their end. However, he was unable to reproduce the problem on his end even after turning on the Tablet PC Input Service on both his PC and a freshly made Windows 7 VM. So while he was able to identify the key players that caused the problem on my PC he was not able to find root cause and hence unable to pursue it further.
This may be attributed to my particular pen tablet device (Wacom) or something else all together. Its unknown. If anyone else encounters this problem, please contact me. The engineer invited me to contact him if I was ever able to narrow down the cause. For now, just keeping the service off prevents the issue.
I have encountered a very similar scenario of a StackOverflowsException in DataGridView.
Conditions:
- A WinForm hosting a datagridview control. DataGridView properties ReadOnly and VirtualMode set to true.
- VirtualMode's OnCellValueNeeded implemented as per MSFT documentation (http://msdn.microsoft.com/en-us/library/2b177d6d.aspx)
- Load a sizable amount of data (15 columns x 1 x 10^5 rows)
- Behavior of datagridview is normal (i.e.: responsiveness of GUI, row and cell selection, vertical & horizontal scrolling) if displaying only 10 Columns X 30 rows [300 cells]. When I maximize the display such that the number of displayed cells is much larger, a StackOverflowsException in DataGridView is fired.
- I, too, have an attached Wacom tablet to my PC.
- The problem disappears if I stop the Tablet PC Input Service (tabtip.exe)
So...in my case, indeed, Franks workaround is in the right direction and supports the idea that 1. the Tablet PC Input Service is a culprit and 2. the number of displayed (active) cells in the screen has an effect on firing the exception.
First of all, thanks to @Frank Weindel for pointing to this WEIRD problem (only microsoft can come up with this).
For those who doesn't want to disable the "Tabtip.exe" as part of the requirement, say your application is for a tablet and only possible input method is Tabtip, there is an workaround.
You can kill the Tabtip at the event where the crash occurs. For me, it is when i select items at row beyond 60,000. This is what I did.
Private Sub DataGridView1_Scroll(sender As Object, e As ScrollEventArgs) Handles DataGridView1.Scroll
Call closeKeyboard()
End Sub
'When a user have to type something in textbox'
Private Sub Lookup_Tbox_MouseDown(sender As Object, e As MouseEventArgs) Handles Lookup_Tbox.MouseDown
Call OpenKeyboard()
End Sub
Public Sub OpenKeyboard()
System.Diagnostics.Process.Start("tabtip.exe")
End Sub
Public Sub closeKeyboard()
Dim proc() As System.Diagnostics.Process = Process.GetProcessesByName("tabtip")
For i As Integer = 0 To proc.Length - 1
proc(i).Kill()
Next i
End Sub
Hope it helps someone :) Happy fighting :)
I am not completly understand ur promblem but I think ur problem is slowness of datagridview and memory
I Have a solution : 1:Break datagridview row into pages like only show maximum 100 row in Datagridview and next hundread in button or other control click it help to reduce ur video memory 2: Enable Double Buffred on to DataGridView 3: Use Suspendlayout and resume layout function to easily draw item
I had the same problem GridView with 50K records. Using the ScrollBar or simply moving large number of records caused the StackOverflowsException in DataGridView. After reading the above I simply stopped the virtual on screen keyboard (my screen is touch screen) Service description "Enables Touch Keyboard and Handwriting Panel pen and ink functionality"
As soon as this was stopped the GridView worked perfectly.
I had exact problem as described in question, after reading here and my own experimenting, this solved my problem:
private void dataGridView1_Scroll(object sender, ScrollEventArgs ex)
{
try
{
dataGridView1.Focus();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
来源:https://stackoverflow.com/questions/14145811/stackoverflowexception-with-datagridview