7

这是一个奇怪的问题。我有一个DataGridView. 我正在使用我自己的自定义类DataSource的包含对象来设置它。List列表中大约有 50,000 个项目。我定义了我希望在设计器中可见的所有列并设置AutoGenerateColumns为 false。

一旦我将它设置DataSource到我的列表中,它就会立即正确填充。我可以上下滚动,选择不同的行。一切都是好的。但是,当我一直向下滚动,然后让包含DataGridView失去焦点的窗口时,一切都冻结了,不久之后堆栈溢出:

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 
    ...

由于某种原因,该DataGridViewRow.DataGridViewRowAccessibleObject.Bounds.get()方法正在将自己称为遗忘。整个堆栈对我来说似乎很奇怪。为什么会Font.Height.get()打电话DataGridViewRow

编辑:

我被要求提供一些代码。这是设计器DataGridView为其及其列生成的代码:

    // 
    // 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;

当需要填充网格视图时,我只需执行以下操作:

dataGridView.DataSource = myList;
4

6 回答 6

11

使固定

目前尚无修复方法。

解决方法

从控制面板中的服务面板禁用Tablet PC 输入服务(aka tabtip.exe)。

细节

几周前,我就这个问题联系了 Microsoft 开发人员支持。我与 WinForms 团队的一位支持工程师通信,我们发现这个问题在某种程度上是由于Microsoft 的Tablet PC Input Service (tabtip.exe)运行时将Accessibility.dll加载到我的应用程序中引起的。此服务至少存在于所有 Windows 7 Enterprise 安装中,但通常仅当您有平板电脑或曾经在您的 PC 上安装过任何类型的笔输入设备时才会运行。我过去曾在我的 PC 上使用过 Wacom Bamboo 数位板,因此运行此服务是有道理的。请注意,已确定我用来填充的方法和我设置的任何属性都与该问题无关。DataGridView

Accessibility.dll是一个 Microsoft 库,它允许某些外围设备(数位板,尤其是辅助设备)更轻松地交互并获取有关表单和包含在表单上的控件的额外信息。我对此不是 100% 确定的,但我相信如果安装了这样的外围设备,这个库会自动加载到每个正在运行的 Windows 进程中。

DataGridView在检查了我提供的转储后,Microsoft 工程师对决定关闭的代码路径感到困惑,并发现Accessibility.dll是让它发生的罪魁祸首。他承认DataGridView不应该这样做,而且这对他们来说似乎是一个问题。但是,即使在他的 PC 和新制作的 Windows 7 虚拟机上打开 Tablet PC 输入服务后,他也无法重现该问题。因此,尽管他能够确定导致我的 PC 出现问题的关键因素,但他无法找到根本原因,因此无法进一步追查。

这可能归因于我的特定数位板设备 (Wacom) 或其他东西。它的未知数。如果其他人遇到此问题,请与我联系。如果我能够缩小原因,工程师邀请我与他联系。目前,只需关闭服务即可防止出现问题。

于 2013-02-05T20:56:10.013 回答
1

我在 DataGridView 中遇到了一个非常相似的 StackOverflowsException 场景。

条件:

  1. 承载 datagridview 控件的 WinForm。DataGridView 属性 ReadOnly 和 VirtualMode 设置为 true。
  2. VirtualMode 的 OnCellValueNeeded 根据 MSFT 文档实现 ( http://msdn.microsoft.com/en-us/library/2b177d6d.aspx )
  3. 加载大量数据(15 列 x 1 x 10^5 行)
  4. 如果仅显示 10 列 X 30 行 [300 个单元格],则 datagridview 的行为是正常的(即:GUI 的响应性、行和单元格选择、垂直和水平滚动)。当我最大化显示以使显示的单元格数量更大时,会触发 DataGridView 中的 StackOverflowsException。
  5. 我也有一个连接到我的 PC 的 Wacom 平板电脑。
  6. 如果我停止 Tablet PC 输入服务 (tabtip.exe),问题就会消失

所以...在我的情况下,的确,弗兰克斯的解决方法是正确的方向,并支持这样的想法:1.平板电脑输入服务是罪魁祸首,2.屏幕中显示(活动)单元格的数量对触发异常。

于 2013-07-04T19:16:05.663 回答
1

首先,感谢@Frank Weindel 指出了这个 WEIRD 问题(只有微软才能提出这个问题)。

对于那些不想禁用“Tabtip.exe”作为要求的一部分的人,假设您的应用程序用于平板电脑并且唯一可能的输入法是 Tabtip,有一种解决方法。

您可以在发生崩溃的事件中终止 Tabtip。对我来说,这是当我选择超过 60,000 行的项目时。这就是我所做的。

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

希望它可以帮助某人:) 战斗愉快:)

于 2015-02-19T11:05:57.640 回答
0

我不完全理解你的问题,但我认为你的问题是 datagridview 和内存的缓慢

我有一个解决方案: 1:将 datagridview 行分成页面,例如在 Datagridview 中仅显示最大 100 行,在按钮或其他控件中单击下一个百个单击它有助于减少您的视频内存 2:在 DataGridView 上启用双缓冲 3:使用 Suspendlayout 和恢复轻松绘制项目的布局功能

于 2013-01-04T10:26:14.417 回答
0

我有同样的问题 GridView 有 50K 记录。使用 ScrollBar 或简单地移动大量记录会导致 DataGridView 中的 StackOverflowsException。阅读完上述内容后,我只是停止了虚拟屏幕键盘(我的屏幕是触摸屏)服务描述“启用触摸键盘和手写面板笔和墨水功能”

一旦停止,GridView 就可以完美运行。

于 2014-11-20T21:32:41.027 回答
0

我遇到了问题中描述的确切问题,在阅读了这里和我自己的实验之后,这解决了我的问题:

private void dataGridView1_Scroll(object sender, ScrollEventArgs ex)
{
    try
    {
         dataGridView1.Focus();
    }
    catch (Exception ex)
    {
         MessageBox.Show(ex.Message);
    }
}
于 2015-04-21T12:18:53.320 回答