.net 在多线程处理期间检索Windows窗体属性
我对VB.NET有点熟悉,但对多线程非常陌生 在这种情况下,我启动了一个与主进程分离的新线程,并使用该新线程创建并显示了一个新表单。新表单的Load()过程中的一个方法是根据主表单(Form1)的位置设置表单的位置 然而,我发现,当我从这个线程中引用Form1的属性时,它们并没有被准确地检索到。特别是,Location.X和Location.Y属性显示为0,而实际上它们是更大的整数.net 在多线程处理期间检索Windows窗体属性,.net,vb.net,multithreading,winforms,.net,Vb.net,Multithreading,Winforms,我对VB.NET有点熟悉,但对多线程非常陌生 在这种情况下,我启动了一个与主进程分离的新线程,并使用该新线程创建并显示了一个新表单。新表单的Load()过程中的一个方法是根据主表单(Form1)的位置设置表单的位置 然而,我发现,当我从这个线程中引用Form1的属性时,它们并没有被准确地检索到。特别是,Location.X和Location.Y属性显示为0,而实际上它们是更大的整数 Private Sub SetLocation() Dim parentx, parenty, pare
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()方法中设置断点时,程序中断调试,X和Y变量将首先在值显示中注册为0:
但是,在调试过程中,如果我在IDE的暂停状态下访问Form1的相关信息,而不恢复应用程序,然后返回查看X和Y值,则属性最终将显示为其实际值
在调试断点期间加载表单属性是否正常?这种现象是VB.NET中多线程的一个已知方面吗?为了让我的新线程访问这些信息,我是否需要经历更复杂的线程通信方法
谢谢大家! 这很难解释,但我会尽力的 在您的用法中,Form1是表单类类型,而不是表单本身 在VB.NET中,这是一种常见且持续的混淆。
My.Forms
仅列出您在项目中定义的表单设计不是活动表单本身。
My.Forms
如果您的项目以Form1开始,VB.NET将创建该表单的实例,该实例具有自己的标识和内存分配。
打开引用初始表单的新表单时,需要通过引用将该标识传递给第二个表单
IMHO最好的方法是扩充Form2的构造函数。如下所示
Public Sub New(owner_Form As Form1)
Owner = owner_Form
' This call is required by the designer.
InitializeComponent()
End Sub
然后在设置位置代码中使用以下命令
parentx = Owner.Location.X
parenty = Owner.Location.Y
parentw = Owner.Width
parenth = Owner.Height
parentx = Main_Form.Location.X
parenty = Main_Form.Location.Y
parentw = Main_Form.Width
parenth = Main_Form.Height
现在:示例代码没有指明启动新表单的线程的位置
如果线程代码是Form1类的一部分,那么只需在线程代码中执行以下操作即可
Dim Form2 as New Form2(me)
如果它比这更深,您需要通过层次结构向下传递Me
如果应用程序不太复杂,另一种方法是使用其他一些全局或共享类引用来标识主窗体
例如:
在全局模块中添加
Public Main_Form as Form1
并在表格1中加载添加
Main_Form = Me
然后在设置位置代码中使用以下命令
parentx = Owner.Location.X
parenty = Owner.Location.Y
parentw = Owner.Width
parenth = Owner.Height
parentx = Main_Form.Location.X
parenty = Main_Form.Location.Y
parentw = Main_Form.Width
parenth = Main_Form.Height
为什么这么复杂
您必须强迫自己记住的是,在执行过程中,您的程序可以创建任意数量的Form1,或者任何其他形式每个人都有自己的身份。
My.Forms
My.Forms仅列出原型
跨线程UI引用
正如Enigmativity所提到的,从非UI线程引用UI可能是一个危险的地方,并且充满了会让你抓狂的问题。我确实同意,通过另一个线程使用UI是非常困难的,但是,如果完全理解模型,那么在某些情况下,这种引用是可以接受的。只读用法,如当前示例就是一个很好的例子
但是,无论第二个表单是从新线程启动的,还是从初始表单派生为普通表单。Show()的,这个“答案”都是相同的
PS:您还可以简化我们的代码
Me.Location = <whatever method you choose>.Location
Me.Size = <whatever method you choose>.Size
Me.Location=.Location
Me.Size=.Size
My.Forms.Form1不是您想象的那样。这是表单模型,而不是实例。您需要在某个地方声明Form1或将其转发给线程。您说,“我已经启动了一个与主进程分离的新线程,并使用该新线程创建并显示了一个新表单”,但这很糟糕。您应该只使用主线程来创建UI元素。仅在处理非UI数据时使用线程。@Enigmativity当数据加载到另一个线程时,我使用一个线程来显示加载屏幕。我知道它在技术上是一个UI元素,但这不是线程的用途之一吗?@Trevor My SetLocation()方法在我从主进程加载此表单时起作用,甚至使用My.Forms.Form1访问表单的属性。你能解释一下为什么它会从主进程而不是从线程工作吗?@Marisha-不,你不应该对UI做任何事情,除非它在主UI线程上。很难把它做好。如果你正在加载数据,你可以在另一个线程上完成。为什么还要让你的UI多线程呢?非常感谢你的回复。我想我理解传递Form1的对象引用的结构,而不仅仅是访问Form1的类,所以如果需要的话,我想我有工具来实现它。不过,我确实希望尽可能彻底地了解它是如何工作的,但我仍然不太明白在调试中断期间看到了什么(在调试中断期间,值最初为0,然后在同一暂停期间不久发生了更改)。为什么会发生这种情况,为什么我停留在主进程线程上时不会发生这种情况?谁知道。。IDE有时会做一些奇怪的事情。我从来没有真正弄清楚起始表单的真正定义。谢谢你的洞察力!嘿@Trevor,我还有一个相关问题,你能帮我吗?我已将加载屏幕放在主线程上,但无法将其居中。结果表明,表单的Location.X和Location.Y值是屏幕坐标,表单