2017-02-20 5 views
1

Я немного знаком с VB.NET, но очень новичок в многопоточности.Получение свойств Windows Form во время многопоточности

У меня возникла ситуация, когда я начал новый поток отдельно от основного процесса, и с этим новым потоком я создал и отобразил новую форму. Одним из методов процедуры Load() новой формы является установка местоположения формы, в зависимости от местоположения основной формы (Form1).

Я нахожу, однако, что, когда я ссылаюсь на свойства Form1 из этого потока, они не точно извлекаются. В частности, свойства Location.X и Location.Y отображаются как 0, когда они на самом деле являются более существенными целыми числами.

Private Sub SetLocation() 

    Dim parentx, parenty, parentw, parenth As Integer 
    Dim parentForm As Form = My.Forms.Form1 

    parentx = parentForm.Location.X 
    parenty = parentForm.Location.Y 

    parentw = parentForm.Width 
    parenth = parentForm.Height 

    Me.Location = New Point(parentx + (parentw/2), parenty + (parenth/2)) 

End Sub 

Часть я нахожу странное об этом заключается в том, что, когда я установить контрольную точку в пределах этого SetLocation() метод, а программа перерывов для отладки, то Х и Y переменные будут сначала зарегистрироваться как 0 на дисплее значений :

x and y zero values

Но тогда, в то время как я отладки, если доступ к информации о Form1 в IDE в его приостановленном состоянии, без возобновления приложения, а затем вернуться к просмотру X и Y значения, свойства в конечном итоге будут отображаться как их фактические значения.

x and y actual values

Является ли это нормальным для свойства формы, которые будут загружены в середине точки отладки разрыва? Является ли это явление известным аспектом многопоточности в VB.NET? И мне придется пройти гораздо более сложные методы связи нити, чтобы мой новый поток мог получить доступ к этой информации?

Спасибо!

+1

My.Forms.Form1 не так, как вы думаете. Это модель формы, а не экземпляр. Вам нужно будет объявить Form1 где-нибудь или передать его в поток. –

+1

Вы говорите: «Я начал новый поток отдельно от основного процесса, и с этим новым потоком я создал и отобразил новую форму», но это плохо.Вы должны использовать только основной поток для создания элементов пользовательского интерфейса. Используйте только потоки при работе с данными, отличными от UI. – Enigmativity

+0

@ Энигматичность Я использую поток для отображения экрана загрузки, когда данные загружаются в другой поток. Я знаю, что это технический элемент UI, но разве это не одно из применений для потоковой передачи? – Marisha

ответ

3

Это трудно объяснить, но я сделаю все возможное.

В вашем использовании Form1 - это тип класса формы, а не сама форма.

Это обычное и постоянное замешательство в VB.NET.

My.Forms 

Списки только форма конструкции вы определили в проекте ... НЕ активные формы. Сам себе

Если ваш проект начинается с Form1, VB.NET создает INSTANCE в той форме, которая имеет свою собственную идентичность и распределения памяти.

Когда вы открываете новую форму, которая ссылается на начальную форму, , вам необходимо передать это удостоверение во вторую форму по ссылке.

Лучший способ сделать это, IMHO - увеличить Конструктор Form2. As Follows.

Public Sub New(owner_Form As Form1) 
    Owner = owner_Form 
    ' This call is required by the designer. 
    InitializeComponent() 

End Sub 

Затем в коде SetLocation с помощью следующей

parentx = Owner.Location.X 
    parenty = Owner.Location.Y 
    parentw = Owner.Width 
    parenth = Owner.Height 

ТЕПЕРЬ: ваш пример кода не указывает, где нить, что начинает новую форму.

Если код потока является частью класса Form1, вы можете просто сделать следующее в своем коде потока.

Dim Form2 as New Form2(me) 

Если это глубже этого, вам нужно будет передать Меня через иерархию.

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

Пример:

В глобальном модуле добавить

Public Main_Form as Form1 

И в Form1_Load добавить

Main_Form = Me 

Затем в коде SetLocation используют следующие

parentx = Main_Form.Location.X 
    parenty = Main_Form.Location.Y 
    parentw = Main_Form.Width 
    parenth = Main_Form.Height 

ПОЧЕМУ ТАК СЛОЖНО

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

В My.Forms указан только прототип.

Перекрестная РЕЗЬБОВОЙ UI СПРАВКА

Как отмечает Enigmativity, ссылаясь на интерфейс из не UI-поток может быть опасным местом, чтобы пойти и чревато проблемами, которые будут вести вас тронутый. Я согласен, что использование пользовательского интерфейса через другой поток наступает на очень тонкий лед, однако есть случаи, когда модель полностью понятна, что такая ссылка приемлема. Используется только чтение, например, текущий пример.

Однако этот «ответ» будет такой же, была ли запущена вторая форма из нового потока или просто порождал как обычный Form.Show() из исходной формы

PS: Вы может также упростить наш код

Me.Location = <whatever method you choose>.Location 
Me.Size = <whatever method you choose>.Size 
+0

Большое спасибо за ваш ответ. Я думаю, что я понимаю структуру передачи объектной ссылки Form1, а не просто доступ к классу Form1, поэтому я думаю, что у меня есть инструменты для реализации, если нужно. Я хочу понять, как это работает как можно тщательнее, хотя, и я до сих пор не совсем понимаю, что я видел во время разрыва отладки (где значения были сначала 0, а затем изменены вскоре после этого в течение той же паузы). Почему это произошло, и почему это не происходит, когда я остаюсь на основной теме процесса? – Marisha

+0

Кто знает, IDE иногда делает некоторые странные вещи. Я никогда не понимал, где форма запуска ДЕЙСТВИТЕЛЬНО определена. –

+0

Хорошо. Спасибо за ваше понимание! – Marisha

Смежные вопросы