Заставка, вызывающая исключение кросс-потоков, если форма запуска закрыта из кода - PullRequest
0 голосов
/ 31 января 2019

Я только что унаследовал унаследованный проект VB.Net, который отлично работает в VS Community 2017 на машине в сети клиента, но когда я пытаюсь выполнить код локально (на VS2017 Pro), я получаю исключение.

В проекте установлены следующие свойства:

  • Экран-заставка: SplashInvoice
  • Форма запуска: SetupWizard

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

Private Sub SetupWizard_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Try
        If [some conditions] Then
            frmMain.Show()
            Me.Close()
        Else

Я получаю эту ошибку, когда выполнение выходит из SetupWizard_Load, если выполнены условия, и me.closeвызываемый:

Произошло необработанное исключение типа 'System.InvalidOperationException' в System.Windows.Forms.dll. Недопустимая операция между потоками: элемент управления «SplashInvoice» доступен из потока, отличного от потока, в котором онбыл создан.

Если я закомментирую бит me.close, все будет работать нормально.

Итак, похоже на закрытие формы запуска проекта во время пр.Заставка oject по-прежнему показывает проблему, которая приводит к нескольким вопросам:

  • Почему это вызывает исключение - не все ли это работает в главном потоке выполнения?
  • Почему это происходит на моем компьютере, а не на компьютере разработчика?

Это полная трассировка стека:

System.Transactions Critical: 0: http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/UnhandledUnhandled exceptionInvoice Generator.exeSystem.InvalidOperationException, mscorlib, Version = 4.0.0.0, Culture = нейтральный, PublicKeyToken = b77a5c561934e089Сопротивление недопустимого потока управления: элемент управления SplashInvoice, доступный из потока, отличного от потока егобыл создан на.в System.Windows.Forms.Control.get_Handle () в System.Windows.Forms.Form.Activate () в Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.HideSplashScreen () в Microsoft.VisualBasic.ApplicationServices.Wase.AdEventArgs e) в System.EventHandler.Invoke (Отправитель объекта, EventArgs e) в System.Windows.Forms.Form.OnLoad (EventArgs e) в System.Windows.Forms.Form.OnCreateControl () в System.Windows.Forms.Control.CreateControl (Boolean fIgnoreVisible)
в System.Windows.Forms.Control.CreateControl () в System.Windows.Forms.Control.WmShowWindow (Message & m) в System.Windows.Forms.Control.WndProc (Message & m) вSystem.Windows.Forms.ScrollableControl.WndProc (Message & m)
в System.Windows.Forms.Form.WmShowWindow (Message & m) в System.Windows.Forms.Form.WndProc (Message & m) в System.Windows.Forms.Control.ControlNativeWindow.OnMessage (Message & m) в System.Windows.Forms.Control.ControlNativeWindow.WndProc (Message & m) в System.Windows.Forms.NativeWindow.DebuggableCallback (IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) System.InvalidOperationException: недопустимая операция между потоками: элемент управления «SplashInvoice» доступен из потока, отличного от потока, в котором он был созданна.в System.Windows.Forms.Control.get_Handle () в System.Windows.Forms.Form.Activate () в Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.HideSplashScreen () в Microsoft.VisualBasic.ApplicationServices.Wase.AdEventArgs e) в System.EventHandler.Invoke (Отправитель объекта, EventArgs e) в System.Windows.Forms.Form.OnLoad (EventArgs e) в System.Windows.Forms.Form.OnCreateControl () в System.Windows.Forms.Control.CreateControl (Boolean fIgnoreVisible)
в System.Windows.Forms.Control.CreateControl () в System.Windows.Forms.Control.WmShowWindow (Message & m) в System.Windows.Forms.Control.WndProc (Message & m) вSystem.Windows.Forms.ScrollableControl.WndProc (Message & m)
в System.Windows.Forms.Form.WmShowWindow (Message & m) вSystem.Windows.Forms.Form.WndProc (Сообщение & m) в System.Windows.Forms.Control.ControlNativeWindow.OnMessage (Сообщение & m) в System.Windows.Forms.Control.ControlNativeWindow.WndProc (Сообщение & m) в System.Windows.Forms.поток, отличный от потока, в котором он был создан.

Программа '[50096] Invoice Generator.exe' вышла с кодом -1 (0xffffffff).

1 Ответ

0 голосов
/ 31 января 2019

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

private sub CloseSplash()

    Dim mySplash = My.Application.OpenForms.Item("SplashInvoice")

    mySplash.Invoke(New MethodInvoker(Sub()
        mySplash.Close()
        mySplash.Dispose()
    End Sub))

End sub

Этот код основан на этом ответе .

@ TnTinMn затемпредоставил некоторую действительно полезную информацию по всем этим комментариям и привел меня к документации Microsoft по Расширение модели приложения Visual Basic

С этой превосходной диаграммой, объясняющей, как все это соединяется вместе:

Visual Basic Application Model with SplashScreen

В этой статье также указывается

ShowSplashScreen.Определяет, имеет ли приложение заданный экран-заставку, и если это так, отображает экран-заставку в отдельном потоке.

, который, по-видимому, является корнем проблемы, которую я вижу.

@ TnMinMn также сделал несколько действительно полезных предложений о том, как решить эту проблему:

Лично я бы отключил Application Framework и использовал бы Sub Main для запуска настроенной версии Microsoft.VisualBasic.ApplicationServices..WindowsFormsApplicationBase.Таким образом, вы можете установить MainForm в зависимости от ваших условий, при этом все еще используя базовую заставку, вместо создания формы, которая никогда не будет отображаться при выполнении некоторых условий

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...