Announcement

Collapse
No announcement yet.

Warum gibt es in einem Fall des DataGridView eine AccessViolationException?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Warum gibt es in einem Fall des DataGridView eine AccessViolationException?

    Ausgangssituation: Im Hauptformular ist ein DataGridView, das als DataSource eine DataTable hat. Je nach aktueller Zeile werden weitere Daten angezeigt. Dazu habe ich das Event RowEnter verwendet. Zusätzlich wird bei einem Doppelklick in einer Zeile des DataGrids ein neues Formular geöffnet, das zeilenspezifisch funktioniert, dazu habe ich das Event
    DoubleClick verwendet.
    Wenn ich auf eine markierte Zeile des DataGridViews doppelklicke, klappt es, aber wenn ich in eine nicht-markierte Zeile doppelklicke bekomme ich eine Acces Violation Exception, die ich leider nicht verstehe oder nachvollziehen kann. Ich habe nur den Fehlertext des Debuggers und ich hoffe, dass ihr mir weiterhelfen könnt, wo der eigentliche Fehler liegt!
    Schaut euch bitte den Fehlertext an und vielleicht habt ihr einen Tip für mich, wie ich die Ursache finde. Natürlich habe ich debuggt, aber der Fehler entsteht erst, nachdem alles korrekt durchlaufen wurde. Es wird sogar alles angezeigt und es dauert ca. 1 bis diese Exception kommt.

    Fehlertext:

    System.Transactions Critical: 0 : <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical"><TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier><Description>Unbehandelte Ausnahme</Description><AppDomain>Userverwaltung.vshost.exe</AppDomain><Exception><ExceptionType>System.AccessV iolationException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.</Message><StackTrace> bei System.Windows.Forms.UnsafeNativeMethods.CallWindo wProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
    bei System.Windows.Forms.NativeWindow.DefWndProc(Messa ge&amp;amp; m)
    bei System.Windows.Forms.ToolTip.WndProc(Message&amp;a mp; msg)
    bei System.Windows.Forms.ToolTip.ToolTipNativeWindow.W ndProc(Message&amp;amp; m)
    bei System.Windows.Forms.NativeWindow.DebuggableCallba ck(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    bei System.Windows.Forms.UnsafeNativeMethods.DispatchM essageW(MSG&amp;amp; msg)
    bei System.Windows.Forms.Application.ComponentManager. System.Windows.Forms.UnsafeNativeMethods.IMsoCompo nentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
    bei System.Windows.Forms.Application.ThreadContext.Run MessageLoopInner(Int32 reason, ApplicationContext context)
    bei System.Windows.Forms.Application.ThreadContext.Run MessageLoop(Int32 reason, ApplicationContext context)
    bei System.Windows.Forms.Application.Run(ApplicationCo ntext context)
    bei Microsoft.VisualBasic.ApplicationServices.WindowsF ormsApplicationBase.OnRun()
    bei Microsoft.VisualBasic.ApplicationServices.WindowsF ormsApplicationBase.DoApplicationModel()
    bei Microsoft.VisualBasic.ApplicationServices.WindowsF ormsApplicationBase.Run(String[] commandLine)
    bei Userverwaltung.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:Zeile 81.
    bei System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
    bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
    bei Microsoft.VisualStudio.HostingProcess.HostProc.Run UsersAssembly()
    bei System.Threading.ThreadHelper.ThreadStart_Context( Object state)
    bei System.Threading.ExecutionContext.Run(ExecutionCon text executionContext, ContextCallback callback, Object state)
    bei System.Threading.ThreadHelper.ThreadStart()</StackTrace><ExceptionString>System.AccessViolation Exception: Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
    bei System.Windows.Forms.UnsafeNativeMethods.CallWindo wProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
    bei System.Windows.Forms.NativeWindow.DefWndProc(Messa ge&amp;amp; m)
    bei System.Windows.Forms.ToolTip.WndProc(Message&amp;a mp; msg)
    bei System.Windows.Forms.ToolTip.ToolTipNativeWindow.W ndProc(Message&amp;amp; m)
    bei System.Windows.Forms.NativeWindow.DebuggableCallba ck(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    bei System.Windows.Forms.UnsafeNativeMethods.DispatchM essageW(MSG&amp;amp; msg)
    bei System.Windows.Forms.Application.ComponentManager. System.Windows.Forms.UnsafeNativeMethods.IMsoCompo nentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
    bei System.Windows.Forms.Application.ThreadContext.Run MessageLoopInner(Int32 reason, ApplicationContext context)
    bei System.Windows.Forms.Application.ThreadContext.Run MessageLoop(Int32 reason, ApplicationContext context)
    bei System.Windows.Forms.Application.Run(ApplicationCo ntext context)
    bei Microsoft.VisualBasic.ApplicationServices.WindowsF ormsApplicationBase.OnRun()
    bei Microsoft.VisualBasic.ApplicationServices.WindowsF ormsApplicationBase.DoApplicationModel()
    bei Microsoft.VisualBasic.ApplicationServices.WindowsF ormsApplicationBase.Run(String[] commandLine)
    bei Userverwaltung.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:Zeile 81.
    bei System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
    bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
    bei Microsoft.VisualStudio.HostingProcess.HostProc.Run UsersAssembly()
    bei System.Threading.ThreadHelper.ThreadStart_Context( Object state)
    bei System.Threading.ExecutionContext.Run(ExecutionCon text executionContext, ContextCallback callback, Object state)
    bei System.Threading.ThreadHelper.ThreadStart()</ExceptionString></Exception></TraceRecord>

  • #2
    Du musst uns ein wenig Code zeigen.

    Was machst du genau in RowEnter und wie hängt das mit DoubleClick zusammen? RowEnter ist zum anzeigen von Daten zur aktuellen Zeile eigentlich ungeeignet denn RowEnter tritt auf bevor die aktuelle Zeile wechselt. Eher geeignet wäre z.b. BindingSource.CurrentChanged.

    In deinem StackTrace taucht die Tooltip Klasse auf. Spielst du selbst an den Tooltips im Grid rum? Und wenn ja zeig wie.

    Comment


    • #3
      Hallo Ralf Jansen
      erst einmal herzlichen Dank für die Antwort. Gestern abend habe ich selbst noch einiges versucht und herausgefunden, an welcher Stelle die Exception kommt und WANN sie genau
      kommt. Diese Exception wird nur ausgelöst, wenn vorher der Fokus auf einem anderen Fenster (weitere Form) dieser Anwendung war und dann in dem besagten dataGridView ein Doppelklick auf eine nicht aktuelle (markierte) Zeile mache. Mache ich dagegen den Doppelklick auf die aktuelle Zeile, gitb es keine Exception. Wenn der Focus vorher bereits die Form mit dem besagten DataGridView war, gibt es überhaupt keine Exception.

      Im Einzelnen ist das die DataGridView.DataSource auf eine DataTable eines DataSets gesetzt, die beim Laden der Form gefüllt wird:

      [highlight=vbnet]
      Option Explicit

      Imports System.Data.Common
      Imports System.Data.SqlClient
      Imports System.Data
      Imports Userverwaltung


      Public Class frmNV

      Protected WithEvents ToolStripMenuItemColumnFilter As ToolStripMenuItem

      'Laden des Formulars und Füllen des Haupt-DataGridViews
      Private Sub frmNV_Load( ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

      Dim clsSQL As clsUserSQL 'SQL-Handling
      clsSQL = New clsUserSQL

      dataGridViewNV.Visible = True
      dataGridViewNV.AutoGenerateColumns = True
      dataGridViewNV.AlternatingRowsDefaultCellStyle.Bac kColor = Color.Lavender
      dataGridViewNV.BackColor = Color.WhiteSmoke
      dataGridViewNV.ForeColor = Color.MidnightBlue
      dataGridViewNV.CellBorderStyle = DataGridViewCellBorderStyle.None
      dataGridViewNV.ColumnHeadersDefaultCellStyle.Font = New Font("Tahoma", 8.0!, FontStyle.Bold)
      dataGridViewNV.ColumnHeadersDefaultCellStyle.BackC olor = Color.MidnightBlue
      dataGridViewNV.ColumnHeadersDefaultCellStyle.ForeC olor = Color.WhiteSmoke
      dataGridViewNV.DefaultCellStyle.ForeColor = Color.MidnightBlue
      dataGridViewNV.DefaultCellStyle.BackColor = Color.WhiteSmoke
      dataGridViewNV.DataSource = clsSQL.GetUser()
      dataGridViewNV.Columns("Kennung").Visible = False 'ID wird nie angezeigt
      dataGridViewNV.Update

      InitializeMenuItemColumnFilter()

      Form1.Show() 'Dummy Form, um Focus einfacher auf anderes Fenster zu bekommen

      End Sub

      'Row-Enter um zwei weitere DataGridView in Abhängigkeit der ausgewählten Zeile zu füllen
      'Was KANN ich denn sonst anstatt RowEnter verwenden???
      Private Sub dataGridViewNV_RowEnter( ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dataGridViewNV.RowEnter
      Dim clsSQL As clsUserSQL
      clsSQL = New clsUserSQL

      Dim strID As String = dataGridViewNV.Rows(e.RowIndex).Cells("Kennung").V alue.ToString ' Wegen dieser Zeile kommt die Exception!!!!!

      ' DataGridView Groups:
      dataGridViewGroups.Visible = True
      dataGridViewGroups.AutoGenerateColumns = True
      dataGridViewGroups.AlternatingRowsDefaultCellStyle .BackColor = Color.Lavender
      dataGridViewGroups.BackColor = Color.WhiteSmoke
      dataGridViewGroups.ForeColor = Color.MidnightBlue
      dataGridViewGroups.CellBorderStyle = DataGridViewCellBorderStyle.None
      dataGridViewGroups.ColumnHeadersDefaultCellStyle.F ont = New Font("Tahoma", 8.0!, FontStyle.Bold)
      dataGridViewGroups.ColumnHeadersDefaultCellStyle.B ackColor = Color.MidnightBlue
      dataGridViewGroups.ColumnHeadersDefaultCellStyle.F oreColor = Color.WhiteSmoke
      dataGridViewGroups.DefaultCellStyle.ForeColor = Color.MidnightBlue
      dataGridViewGroups.DefaultCellStyle.BackColor = Color.WhiteSmoke
      dataGridViewGroups.DefaultCellStyle.SelectionBackC olor = Color.WhiteSmoke
      dataGridViewGroups.DefaultCellStyle.SelectionForeC olor = Color.MidnightBlue
      dataGridViewGroups.DataSource = clsSQL.GetUserGroups(strID)
      dataGridViewGroups.Columns("NutzerID").Visible = False 'ID wird nie angezeigt
      dataGridViewGroups.Columns("GruppenID").Visible = False 'ID wird nie angezeigt
      dataGridViewGroups.Columns("Gruppenbeschreibung"). Visible = False 'ID wird nie angezeigt
      dataGridViewGroups.Update

      ' DataGridView Rights:
      dataGridViewRights.Visible = True
      dataGridViewRights.AutoGenerateColumns = True
      dataGridViewRights.AlternatingRowsDefaultCellStyle .BackColor = Color.Lavender
      dataGridViewRights.BackColor = Color.WhiteSmoke
      dataGridViewRights.ForeColor = Color.MidnightBlue
      dataGridViewRights.CellBorderStyle = DataGridViewCellBorderStyle.None
      dataGridViewRights.ColumnHeadersDefaultCellStyle.F ont = New Font("Tahoma", 8.0!, FontStyle.Bold)
      dataGridViewRights.ColumnHeadersDefaultCellStyle.B ackColor = Color.MidnightBlue
      dataGridViewRights.ColumnHeadersDefaultCellStyle.F oreColor = Color.WhiteSmoke
      dataGridViewRights.DefaultCellStyle.ForeColor = Color.MidnightBlue
      dataGridViewRights.DefaultCellStyle.BackColor = Color.WhiteSmoke

      ' Set the selection background color for all the cells.
      dataGridViewRights.DefaultCellStyle.SelectionBackC olor = Color.WhiteSmoke
      dataGridViewRights.DefaultCellStyle.SelectionForeC olor = Color.MidnightBlue

      dataGridViewRights.DataSource = clsSQL.GetUserRights(strID)

      dataGridViewRights.Columns("NutzerID").Visible = False 'ID wird nie angezeigt
      dataGridViewRights.Columns("RechteID").Visible = False 'ID wird nie angezeigt
      dataGridViewRights.Columns("Rechtebeschreibung").V isible = False 'ID wird nie angezeigt
      dataGridViewRights.Update
      End Sub

      'Die Gründe, warum ich die TooTip benötige:
      Private Sub dataGridViewGroups_CellToolTipTextNeeded( ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellToolTipTextNe ededEventArgs) Handles dataGridViewGroups.CellToolTipTextNeeded
      if e.RowIndex >= 0 AND e.ColumnIndex >= 0 then
      e.ToolTipText = dataGridViewGroups.Rows(e.RowIndex).Cells("Gruppen beschreibung").Value
      End If
      End Sub

      Private Sub DataGridViewRights_CellToolTipTextNeeded( ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellToolTipTextNe ededEventArgs) Handles DataGridViewRights.CellToolTipTextNeeded
      if e.RowIndex >= 0 AND e.ColumnIndex >= 0 then
      e.ToolTipText = dataGridViewRights.Rows(e.RowIndex).Cells("Rechteb eschreibung").Value
      End If
      End Sub

      'Doppelklick-Event , um Eingabe-Form mit den Daten der aktuellen Zeile zu öffnen:
      Private Sub dataGridViewNV_DoubleClick( ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dataGridViewNV.DoubleClick
      Dim clsEditForm As clsUserEditForm
      clsEditForm = New clsUserEditForm
      clsEditForm.ShowEditForm(dataGridViewNV.CurrentRow )
      End Sub

      End Class 'frmNV

      'Ausschnitt der SQL-Klasse
      Imports System.Data.SqlClient

      Public Class clsUserSQL
      '...
      Protected Function InitializeTable(strTableName, strSQL) As DataTable
      Dim cmd As SqlCommand
      Dim da As SqlDataAdapter
      Dim ds As DataSet

      conSQL = New SqlConnection(strConnection)

      cmd = New SqlCommand(strSQL, conSQL)
      da = New SqlDataAdapter(cmd)
      ds = New DataSet

      Try

      if conSQL.State = ConnectionState.Closed then conSQL.Open()
      da.Fill(ds, strTableName)

      Catch sqlExc As SqlException
      MessageBox.Show(sqlExc.ToString, "SQL Exception Error!", _
      MessageBoxButtons.OK, MessageBoxIcon.Error)

      Catch invsqlExc As InvalidOperationException
      MessageBox.Show(invsqlExc.ToString, "SQL Invalid Operation Error!", _
      MessageBoxButtons.OK, MessageBoxIcon.Information)

      Catch exc As Exception
      MsgBox(exc.Message, MsgBoxStyle.OKOnly, "Verbindung zur Datenbank fehlgeschlagen!")

      End Try

      if ds.Tables.Contains(strTableName) then return ds.Tables(strTableName) else return Nothing
      End Function

      ReadOnly Property GetUser(ByVal strID As String) As DataTable
      Get
      Dim strSQL = strSQLUser & " WHERE ID = " & strID
      return InitializeTable(strTableNameUser, strSQL)
      End Get
      End Property

      ReadOnly Property GetGroups() As DataTable
      Get
      return InitializeTable(strTableNameGroups, strSQLGroups)
      End Get
      End Property
      ReadOnly Property GetRights() As DataTable
      Get
      return InitializeTable(strTableNameRights, strSQLRights)
      End Get
      End Property
      End Class 'clsUserSQL
      [/highlight]


      Das ist im wesentlichen das Projekt. Die EditForm beim Doppelklick wird ebenfalls über eine Klasse instanziiert, damit ich für jeden Doppelklick eine neue Fenster-Instanz bekomme. Sonst passiert da zur Zeit weiter nichts. Ich hoffe, dass ich nun alle notwendigen Infos für weitere Hilfe geliefert habe. Vielen Dank!

      Comment


      • #4
        Sorry, die GetUser- Funktion wird hier natürlich auch ohne Parameter benötigt und natürlich gibt es eine Property dazu, hatt ich vergessen, mit anzugeben:

        [highlight=vbnet]
        ReadOnly Property GetUser() As DataTable
        Get
        return InitializeTable(strTableNameUser, strSQLUser)
        End Get
        End Property
        [/highlight]

        Comment


        • #5
          Mal so ins blaue:

          clsEditForm.ShowEditForm(dataGridViewNV.CurrentRow)

          Weil CurrentRow (üblicherweise die aktive Zeile) eben die markierte ist und nicht die, auf die ein Doppelclick ausgeführt wurde. Also sollte der Methode nicht die aktiveZeile, sondern u.U. SelectedRows übergeben werden
          Christian

          Comment


          • #6
            Hallo Christian Marquardt,
            danke für die Antwort und den Tip. Den werde ich in Zukunft berücksichtigen. Bisher klappte das aber mit CurrentRow auch und leider ist das nicht die Stelle, wo der Fehler auftritt.
            Selbst wenn ich nur ein leeres Formular aufrufe anstelle des gewünschten, gibt es diese Exception. Ich glaube, dass der Fehler im Ablauf der Ereignisse im Verborgenen liegt und diesen Ablauf kann ich ja nicht debuggen. Also was wann wo (threadsicher oder nicht) aufgerufen und durchlaufen wird. Vermutlich liegt ein Gedankenfehler von mir vor, aber den finde ich selbst einfach nicht und deshalb hoffe ich auf die Hilfe dieses Forums mit den Entwickler-Experten!

            Comment


            • #7
              Könntest du mal den Code in deinen CellToolTipTextNeeded Events auskommentieren? Einfach nur um zu sehen ob es wie der Callstack vermuten lässt wirklich aus der Tooltip Ecke kommt.

              Comment


              • #8
                Hallo Ralf Jansen,
                du hast/Sie haben mir den entscheidenen Hinweis gegeben. Alle 3 DataGridViews des Hauptformulars verwenden dieses Ereignis, um zeilen- und spaltenbezogene Informationen anzuzeigen. Das DataGridView des EditFormulars ebenfalls. Wenn ich den Code in der Ereignis-Methode CellToolTipTextNeeded für das Hauptgrid auskommentiere, gibt es in der Tat keine Exception mehr. Alle anderen DataGridViews verwenden sie weiterhin problemlos.

                Was ist das Problem bei der ToolTip-Sache? Ich habe die Verwendung als solches aus der MSDN-Hilfe bekommen und finde sie eigentlich nützlich und liegt der Fehler trotzdem woanders? Warum ist das debuggen unter .net so schwierig, zumindest ist das meine Meinung (vorher habe ich mit VS Studio C++ gearbeitet und da konnte man bis ziemlich in die WinAPI-Eingeweide debuggen)

                Also erstmal herzlichen Dank, ich selbst wäre da nicht drauf gekommen!

                Comment


                • #9
                  Warum ist das debuggen unter .net so schwierig, zumindest ist das meine Meinung
                  Du kannst den Symbolserver von Microsoft einschalten dann kannst du zumindest in einen großen Teil des Frameworks reindebuggen. Oder den Reflector kaufen dann kannst du durch jede Assembly(wenn sie nicht gerade mit irgendwelchen abstrusen Methoden obfuscated ist) debuggen.

                  In deinem speziellen Fall hier hast du wahrscheinlich den sprichwörtlichen großen Griff ins Klo getätigt. Normalerweise sollte man nicht solche Problem haben und ich sehe auch keinen grundsätzlichen Fehler in deiner herangehensweise. Hier im speziellen wird wohl irgendwo im Übergang von managed zu unmanaged Code was schief laufen und dieser Teil ist halbmagisch und schwer bis gar nicht zu debuggen . Du könntest ein paar Alternativen durchprobieren. z.b. CellToolTipTextNeeded durch CellEnter ersetzen und von dort selber mit der ToolTip Klasse arbeiten oder in DoubleClick explizit die Tooltipanzeige beenden(wenn das beim Grid geht) bevor du die andere Form öffnest. Oder die Form nicht direkt aus dem DoubleClick öffnen sondern über einen Timer so das die gesamte DoubleClick Funktionalität beendet ist bevor die Form aufgeht etc. Nebenbei könntest du auch wenn das nicht weiterführt einen Supportfall bei Microsoft aufmachen.

                  PS. der Form1.Show() Befehl im Load Event ist verdächtig. Im Load Event ist die gerade aktive Form dabei sich anzuzeigen und versucht selbst noch den Focus zu bekommen. Da am Focus rumzuspielen (z.B durch anzeigen einer anderen Form) ist gefährlich. Das sollte eher im Shown Event passieren. Der Rest des Codes im Load Event, zumindest das Laden der Daten, würde ich auch eher nach Shown verlegen.

                  Comment


                  • #10
                    Hallo Ralf Jansen,
                    danke für die ausführliche Erklärung zum Debuggen. Ich werde einiges davon ausprobieren, da ich auf diese Funktionsweise in dem Projekt weiter aufbauen werde/muss und ich mag keine unliebsamen Überraschungen (zumindest möchte ich sie in Grenzen halten).

                    Das mit Form1.Show() im Load der anderen Form war nur ein Ersatz, um auszuschließen, dass das Öffnen des EditFormulars mit den übergegeben Daten nicht für die Ursache verantwortlich ist.
                    Ich habe bei all' dem Debuggen und Fehlersuche (na, was positives haben ja solche Fehler doch noch, da man auch viel in der Hilfe herumkramt und ausprobiert!) ebenfalls diese Methode Shown entdeckt, die kannte ich vorher nicht und werde sie entsprechend nutzen.

                    Diesen MS Symbolserver kenne ich noch gar nicht, vermutlich braucht man eine Internet-Verbindung um ihn zu verwenden, oder? Mein Entwicklungs-PC ist Standalone bzw. LAN und ich gehe nur mit einem sehr alten PC ins Internet.

                    Auf jeden Fall herzlichen Dank für die Hilfe und ein angenehmenes WE!

                    Leider habe ich öfter das Glück...
                    In deinem speziellen Fall hier hast du wahrscheinlich den sprichwörtlichen großen Griff ins Klo getätigt.
                    ... und hätte nicht gedacht, beim Verwenden von VB.net auch so schnell dieses Glück zu haben!

                    Comment

                    Working...
                    X