3

Ich habe eine saubere WindowsFormsApplication-Lösung erstellt, dem Hauptformular eine hinzugefügt und einen Button darauf platziert.Warum wird eine NullReferenceException ausgelöst, wenn zweimal auf eine ToolStrip-Schaltfläche geklickt wird - openFileDialog.showDialog()?

private void toolStripButton1_Click(object sender, EventArgs e) 
{ 
    openFileDialog1.ShowDialog(); 
} 

Ich habe nicht ändern andere Eigenschaften oder Ereignisse: Ich habe auch eine OpenFileDialog, so dass das Click Ereignis des ToolStripButton sieht wie folgt hinzugefügt.

Die lustige Sache ist, dass, wenn ich die ToolStripButton doppelklicke (der zweite Klick muss ziemlich schnell sein, bevor der Dialog öffnet), dann beide Dialoge abzubrechen (oder wählen Sie eine Datei, ist es nicht wirklich wichtig) und dann Klicken Sie in den Client-Bereich des Hauptformulars, ein NullReferenceException stürzt die Anwendung (Fehlerdetails am Ende des Beitrags angehängt). Bitte beachten Sie, dass das Ereignis Click implementiert ist, während DoubleClick nicht ist.

Was noch seltsamer ist, dass, wenn die OpenFileDialog von jedem Benutzer implementierter Form ersetzt wird, die ToolStripButtonaus Blöcken zweimal angeklickt werden.

Ich verwende VS2008 mit .NET3.5 auf Windows 7 Professional (von MSDNAA) mit den neuesten Updates. Ich habe nicht viele Optionen in VS (nur Schriftgröße, Arbeitsbereich Ordner und Zeilennummerierung) geändert.

Weiß jemand, wie man das löst? Es ist 100% replizierbar auf meiner Maschine, ist es auch auf anderen?

Eine Lösung, die ich mir vorstellen kann, ist das Deaktivieren der Schaltfläche vor dem Aufruf OpenFileDialog.ShowDialog() und dann die Schaltfläche wieder aktivieren (aber es ist nicht nett). Irgendwelche anderen Ideen?

Und jetzt die versprochenen Fehlerdetails:

System.NullReferenceException wurde nicht behandelt
Message = „Objektverweis nicht auf eine Instanz eines Objekts festgelegt.“
Source = "System.Windows.Forms"
Stacktrace:
bei System.Windows.Forms.NativeWindow.WindowClass.Callback (IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
bei System.Windows.Forms .UnsafeNativeMethods.PeekMessage (MSG & msg, HandleRef HWND, Int32 msgMin, Int32 msgmax, Int32 entfernen)
bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop (Int32 DwComponentID, Int32 Grund, Int32 pvLoopData)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner (Int32 Grund, ApplicationContext Kontext)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop (Int32 Grund Application Kontext)
bei System.Windows.Forms.Application.Run (Form Mainform)
bei WindowsFormsApplication1.Program.Main() w C: \ Benutzer \ Marchewek \ Desktop \ Workspaces \ Visual \ WindowsFormsApplication1 \ Program.cs: Zeile 20
bei System.AppDomain._nExecuteAssembly (Assembly Baugruppe, String [] args)
bei System.AppDomain.ExecuteAssembly (String assembly, Evidence assemblySecurity , String [] args)
bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
bei System.Threading.ThreadHelper.ThreadStart_Context (Object state)
bei System.Threading.ExecutionContext.Run (ExecutionContext ExecutionContext, Context Rückruf, Objektzustand)
bei System.Threading. ThreadHelper.ThreadStart()
Innerexception:

+0

VS-Optionen sind irrelevant. Dies sieht wie ein Fehler im Framework aus. – SLaks

+0

Ich konnte Ihr Problem nicht mit VS2008 unter W2K3 und VS2010 unter W2K8 replizieren. –

+0

Repro auch nicht mit XPsp3, VS2008 und .NET2.0 oder 3.5 – Andy

Antwort

2

ich in der Lage war, so etwas wie dies auf einem Windows-7-Maschine zu replizieren - ich habe nicht Ausnahme der aber meine Form wird nicht mehr neu gezeichnet werden. Es kann sein, dass, weil ich nicht in einem Debugger auf der Win 7-Box läuft, dass die Ausnahme verschluckt wird.

Dies passiert nicht auf meinem XP-Rechner. Dies ist nur passiert, wenn ich den toolStripButton benutzt habe und doppelt darauf geklickt habe, als ich das Dialogfeld das erste Mal geöffnet habe. Wenn ich den Dialog normal geöffnet und dann erst geschlossen habe, öffnet der Doppelklick den Dialog nicht zweimal.

ich vermuten, dass das, was hier geschieht ähnlich ist zu einer Race-Condition - wo der Framework-Entwickler nie erwartet, dass ihr Code zweimal eingegeben werden können, aber das wegen eines neuen Anruf wieder in die Nachrichtenschleife aufgetreten ist . Warum passiert das - sieht für mich wie ein Käfer aus.

Ich fand eine ziemlich einfache Problemumgehung, die es verhindert - Aktivieren Sie die DoubleClickEnabled-Eigenschaft des toolStripButton. Sie müssen den Doppelklick-Handler nicht implementieren - er behandelt den Doppelklick als einen einzigen Klick und alles funktioniert.

Ich würde damit umgehen so:

public Form1() 
    { 
     InitializeComponent(); 

     // This is a workaround for a framework bug 
     // see blah blah 
     toolStripButton1.DoubleClickEnabled = true; 

    } 

Nächstes Mal, wenn Sie ein Upgrade-Frameworks Sie versuchen, es zu entfernen können.

Neil

0

Die Showdialog-Methode ist modal. Normalerweise, nachdem ShowDialog aufgerufen wurde, hat der OpenFileDialog den exklusiven UI-Fokus der Anwendung, bis der Dialog geschlossen wird.

Durch einen schnellen Doppelklick auf die Schaltfläche rufen Sie ShowDialog erneut auf, bevor das Framework die Möglichkeit hatte, den OpenFileDialog exklusiven UI-Fokus zu geben. Dies hat Ihre Anwendung in einen ungültigen Zustand versetzt.

Obwohl dies nicht möglich sein sollte, ist es eindeutig, und jetzt ist es dein Problem. Entweder abonnieren Sie das Click-Ereignis der Schaltfläche und deaktivieren Sie die Schaltfläche nach dem ersten Klick; oder entfernen Sie den OpenFileDialog aus dem Designer und erstellen Sie ihn programmgesteuert in Ihrem Click-Handler. Wenn Sie das letztere tun, wickeln Sie es in einem mit Block Garbage Collection, um sicherzustellen:

private void toolStripButton1_Click(object sender, EventArgs e) 
{ 
    using(var OFD = new OpenFileDialog()) 
    { 
     OFD.ShowDialog(); 
    } 
} 
0

Bildschirmauflösung kann einer der Gründe sein, die Fehler im Rahmen verursachen. In meinem Fall habe ich meine Bildschirmauflösung geändert und das Problem wurde nicht in dieser Auflösung produziert und wann immer ich zurück zur empfohlenen Auflösung gehe, bekam ich das Problem.