我想要在多线程操作时正确地调用主程序的属性,但是当我从新线程中用 Form1来返回主程序的属性时,却只能返回0。
在测试中发现当从新线程中,通过类ClassTestNewThread来访问主程序对象Form1时,程序会重新初始化一个Form1的实例,并返回其相应的属性值(但是这个新的Form1实例没有触发Load事件,所以其属性testProperty的值为0)。
所以问题就是:如何在跨线程操作时正确地获取主程序的初始实例对象。
Imports System.Threading
Public Class Form1
#Region " --- InitializeComponent 程序初始界面设置 "
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.btnMainThread = New System.Windows.Forms.Button()
Me.btnNewThread = New System.Windows.Forms.Button()
Me.SuspendLayout()
'
'btnMainThread
'
Me.btnMainThread.Location = New System.Drawing.Point(12, 12)
Me.btnMainThread.Name = "btnMainThread"
Me.btnMainThread.Size = New System.Drawing.Size(75, 23)
Me.btnMainThread.TabIndex = 0
Me.btnMainThread.Text = "主线程"
Me.btnMainThread.UseVisualStyleBackColor = True
'
'btnNewThread
'
Me.btnNewThread.Location = New System.Drawing.Point(93, 12)
Me.btnNewThread.Name = "btnNewThread"
Me.btnNewThread.Size = New System.Drawing.Size(75, 23)
Me.btnNewThread.TabIndex = 1
Me.btnNewThread.Text = "新线程"
Me.btnNewThread.UseVisualStyleBackColor = True
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 12.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(177, 43)
Me.Controls.Add(Me.btnNewThread)
Me.Controls.Add(Me.btnMainThread)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
Friend WithEvents btnMainThread As System.Windows.Forms.Button
Friend WithEvents btnNewThread As System.Windows.Forms.Button
#End Region
'在窗口的Load中设置其初始值为555
Public Property testProperty As Integer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Thread.CurrentThread.Name = "Main thread"
testProperty = 555
Debug.Print("testProperty属性的初始值为 : " & Me.testProperty.ToString)
End Sub
'主线程操作
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btnMainThread.Click
Dim a As New ClassTestNewThread
End Sub
'新线程操作
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles btnNewThread.Click
Dim thd As New Thread(AddressOf Me.ttt)
thd.Name = "New thread"
thd.Start()
End Sub
Private Sub ttt()
Dim a As New ClassTestNewThread
End Sub
End Class
' =========================================
Public Class ClassTestNewThread
Public Sub New()
Dim thd As Thread = Thread.CurrentThread
Debug.Print("Current thread: " & thd.Name)
' 尝试调用主程序Form1的属性,在主线程中可以正确返回其值555,
' 而在新线程中只能返回integer类型的初始值0.
Debug.Print("testProperty属性值为 : " & Form1.testProperty.ToString)
End Sub
End Class
最后的输出结果为:
testProperty属性的初始值为 : 555
Current thread: Main thread
testProperty属性值为 : 555
Current thread: New thread
testProperty属性值为 : 0
------解决思路----------------------
因为你所谓的主线程,根本就是把代码写在form1这个类里了,而不是新建一个类,这个跟线程真的没有关系
而且,类里要使用主线程的属性,你应该将属性传递进类里,而不是类里去获取
好比你写个方法,有形参和实参,你传参数进去就好了,而不是定义一个无参数的方法,然后到方法里面才纠结参数该从哪里获取
------解决思路----------------------
不要说什么"主程序",你根本也没有子程序
你是说主窗体吧
你可以再定义一个static类型的类,里面放上public static类型的变量
------解决思路----------------------
您的问题是这样。
请不要把Public Property testProperty As Integer属性设置在Load加载事件里。
Load事件只能窗体启动时触发一次,所以,不能任意触发它。
解决方案是把Public Property testProperty As Integer直接设置成`
Public Shared Property testProperty As Integer = 555
这样解决问题了。
------解决思路----------------------
调用 Form1 永远不会出错,这是会自动创建的实例。
你可以想象成编译器自动添加了 Public Form1 As New Form1 的定义。
只不过这个定义不是整个进程全局的、而是分线程全局的。
所以你两个 ClassTestNewThread 中调用的是不同的两个 Form1 实例。