StackOverflowException с DataGridView

это странно. У меня есть 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?

EDIT:

меня попросили какой-то код. Это сгенерированный дизайнером код для 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;

6 ответов


исправить

в настоящее время не известно никаких исправлений.

решение

отключить служба ввода планшетных ПК (a.к. a. tabtip.exe) из панели в Панель управления.

подробности

несколько недель назад я связался с поддержкой разработчиков Microsoft по этой проблеме. Я переписывался с инженером поддержки в команде WinForms, и мы выяснили, что эта проблема была каким-то образом вызвана доступность.dll файлы загружается в мое приложение всякий раз, когда Microsoft Tablet PC Input Service (tabtip.exe). Эта служба присутствует по крайней мере на всех установках Windows 7 Enterprise, но, как правило, работает только если у вас есть планшетный ПК или когда-либо устанавливали какой-либо пера устройства ввода на вашем компьютере. В прошлом я использовал планшет Wacom Bamboo pen на своем ПК, поэтому было понятно, почему эта служба работает. обратите внимание, что было определено, что ни метод, который я использовал для заполнения DataGridView ни одно из свойств, которые я установил, не имело ничего общего с проблемой.

доступность.dll файлы - это библиотека Microsoft, которая позволяет некоторым периферийным устройствам (планшетам и особенно вспомогательным устройствам) легче взаимодействовать и получать дополнительную информацию о формах и элементах управления, содержащихся в формах. Я не уверен на 100% в этом, но я считаю, что эта библиотека загружается в каждый запущенный процесс Windows автоматически если такое периферийное устройство установлено.

после изучения дампа, который я предоставил, инженер Microsoft был озадачен путем кода, который DataGridView решил спуститься и обнаружил, что доступность.dll файлы был виновником, который позволил этому случиться. Он признал это DataGridView не должен делать этого, и это казалось проблемой с их стороны. Однако он не смог воспроизвести проблему на своем конце даже после включения службы ввода планшетного ПК на обоих его ПК и свежеприготовленная Windows 7 VM. Поэтому, хотя он смог определить ключевых игроков, которые вызвали проблему на моем компьютере, он не смог найти первопричину и, следовательно, не смог продолжить ее.

Это может быть связано с моим конкретным планшетным устройством (Wacom) или чем-то еще вместе. Это неизвестно. Если кто-то еще сталкивается с этой проблемой, пожалуйста, свяжитесь со мной. Инженер предложил мне связаться с ним, если я смогу сузить круг подозреваемых. Сейчас просто поддерживаю service off предотвращает проблему.


Я столкнулся с очень похожим сценарием StackOverflowsException в DataGridView.

условия:

  1. WinForm с элементом управления datagridview. Свойств datagridview readonly и VirtualMode значение true.
  2. VirtualMode OnCellValueNeeded реализован в соответствии с документацией MSFT (http://msdn.microsoft.com/en-us/library/2b177d6d.aspx)
  3. загрузите значительный объем данных (15 столбцов x 1 x 10^5 rows)
  4. поведение datagridview нормально (т. е.: отзывчивость GUI, выбор строки и ячейки, вертикальная и горизонтальная прокрутка), если отображается только 10 столбцов X 30 строк [300 ячеек]. Когда я максимизирую отображение так, чтобы количество отображаемых ячеек было намного больше, stackoverflowsexception в DataGridView запускается.
  5. у меня тоже есть прикрепленный планшет Wacom к моему компьютеру.
  6. проблема исчезнет, если я остановлю службу ввода планшетного ПК (tabtip.exe)

Итак...в моем случае, действительно, обходной путь франков находится в правильном направлении и поддерживает идею, что 1. служба ввода планшетных ПК является виновником и 2. количество отображаемых (активных) ячеек на экране влияет на запуск исключения.


прежде всего, спасибо @Frank Weindel за указание на эту странную проблему (только microsoft может придумать это).

для тех, кто не хочет отключать "Tabtip.exe " в рамках требования, скажем, ваше приложение для планшета и только возможный метод ввода 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

надеюсь, это поможет кому-то:) Happy fighting:)


Я не полностью понимаю UR promblem, но я думаю, что проблема ur-это медлительность datagridview и памяти

У меня есть решение : 1: разбейте строку datagridview на страницы, такие как только показать максимум 100 строк в Datagridview и далее сотню в кнопке или другом элементе управления нажмите на нее, чтобы уменьшить объем видеопамяти ur 2. включение двойной Buffred на элементе управления datagridview 3: Используйте Suspendlayout и возобновите функцию макета, чтобы легко нарисовать элемент


У меня была такая же проблема GridView с записями 50K. Использование полосы прокрутки или просто перемещение большого количества записей вызвало исключение StackOverflowsException в DataGridView. После прочтения выше я просто остановил виртуальную экранную клавиатуру (мой экран-сенсорный экран) описание службы "включает сенсорную клавиатуру и функциональность панели рукописного ввода и чернил"

Как только это было остановлено, GridView работал отлично.


У меня была точная проблема, как описано в вопросе, после прочтения здесь и моих собственных экспериментов, это решило мою проблему:

private void dataGridView1_Scroll(object sender, ScrollEventArgs ex)
{
    try
    {
         dataGridView1.Focus();
    }
    catch (Exception ex)
    {
         MessageBox.Show(ex.Message);
    }
}