Почему возникает исключение NullReferenceException при двойном нажатии кнопки ToolStrip - openFileDialog.showDialog ()? - PullRequest
3 голосов
/ 02 января 2011

Я создал чистое решение WindowsFormsApplication, добавил ToolStrip в основную форму и поместил на нее одну кнопку. Я также добавил OpenFileDialog, так что событие Click для ToolStripButton выглядит следующим образом:

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

Я не изменил никаких других свойств или событий.

Самое смешное, что когда я дважды щелкаю ToolStripButton (второй щелчок должен быть достаточно быстрым, прежде чем откроется диалоговое окно), затем отменяю оба диалога (или выбираю файл, это не имеет большого значения) и затем щелкните в клиентской области главной формы, приложение NullReferenceException завершит работу приложения (подробности об ошибках приведены в конце публикации). Обратите внимание, что событие Click реализовано, а DoubleClick не равно .

Что еще более странно, когда OpenFileDialog заменяется какой-либо созданной пользователем формой, ToolStripButton блокируется от двойного нажатия .

Я использую VS2008 с .NET3.5 на Windows 7 Professional (от MSDNAA) с последними обновлениями. Я не изменил много параметров в VS (только размер шрифта, папка рабочего пространства и нумерация строк).

Кто-нибудь знает, как это решить? Это 100% тиражируется на моей машине, на других тоже?

Одним из решений, которое я могу придумать, является отключение кнопки перед вызовом OpenFileDialog.ShowDialog() и последующее включение кнопки назад (но это нехорошо). Есть еще идеи?

А теперь обещанные подробности об ошибке:

Исключение System.NullReferenceException не обработано
Сообщение = "Ссылка на объект не установлена ​​для экземпляра объекта."
Источник = "System.Windows.Forms"
StackTrace:
в System.Windows.Forms.NativeWindow.WindowClass.Callback (IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
в System.Windows.Forms.UnsafeNativeMethods.PeekMessage (MSG & msg, HandleRef hwnd, Int32 msgMin, Int32 msgMax, Int32 удалить)
в System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop (Int32 dwComponentID, причина Int32, Int32 pvLoopData)
в System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner (причина Int32, контекст ApplicationContext)
в System.Windows.Forms.Application.ThreadContext.RunMessageLoop (причина Int32, контекст ApplicationContext)
в System.Windows.Forms.Application.Run (форма mainForm)
в WindowsFormsApplication1.Program.Main () w C: \ Users \ Marchewek \ Desktop \ Workspaces \ VisualStudio \ WindowsFormsApplication1 \ Program.cs: строка 20
в System.AppDomain._nExecuteAssembly (сборка сборки, аргументы String [])
в System.AppDomain.ExecuteAssembly (String assemblyFile, Evidence AssemblySecurity, String [] args)
в Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly ()
в System.Threading.ThreadHelper.ThreadStart_Context (состояние объекта)
в System.Threading.ExecutionContext.Run (ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта)
в System.Threading.ThreadHelper.ThreadStart ()
InnerException:

Ответы [ 3 ]

2 голосов
/ 11 января 2011

Мне удалось воспроизвести нечто подобное на Windows 7 Machine - я не получаю исключения, но моя форма больше не будет перерисовываться. Возможно, из-за того, что я не работаю в отладчике на коробке с win 7, исключение проглатывается.

Этого не происходит на моей машине с XP. Это произошло только тогда, когда я использовал toolStripButton и дважды щелкнул по нему при первом открытии диалога. Если я нормально открыл диалоговое окно, а затем сначала закрыл его, то двойной щелчок не открывает диалоговое окно дважды.

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

Я нашел один довольно простой обходной путь, который останавливает его - включите свойство DoubleClickEnabled toolStripButton. Вам не нужно реализовывать обработчик двойного щелчка - он обрабатывает двойной щелчок как один щелчок, и все работает.

Я бы справился с этим так:

    public Form1()
    {
        InitializeComponent();

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

    }

В следующий раз, когда вы обновите фреймворки, вы можете попытаться удалить его.

Neil

0 голосов
/ 15 июня 2016

Разрешение экрана может быть одной из причин, вызывающих ошибку в фреймворке. В моем случае я изменил разрешение экрана, и проблема не возникла в этом разрешении, и когда я возвращался к рекомендованному разрешению, я получал проблему.

0 голосов
/ 11 января 2011

Метод ShowDialog является модальным.Обычно после вызова ShowDialog OpenFileDialog имеет эксклюзивный UI-фокус приложения, пока диалоговое окно не будет закрыто.

Быстро дважды щелкнув кнопку, вы снова вызываете ShowDialog, прежде чем фреймворк сможет предоставить OpenFileDialog эксклюзивныйUI фокус.Это привело ваше приложение в недопустимое состояние.

Хотя это не должно быть возможным, ясно, что это так, и теперь это ваша проблема.Либо подпишитесь на событие Click кнопки и отключите кнопку после первого щелчка;или удалите OpenFileDialog из Designer и создайте его программно в вашем обработчике Click.Если вы сделаете последнее, поместите его в блок using, чтобы обеспечить сборку мусора:

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