从另一个线程VB.net在主线程上打开窗体
我有一个在我们的软件(VB.NET)中运行的自定义通知。通知将在新线程中打开,因此当通知淡入或淡出时,用户仍可以与软件交互 我希望用户能够单击通知并在主线程上打开表单。当我使用普通的从另一个线程VB.net在主线程上打开窗体,.net,vb.net,winforms,.net,Vb.net,Winforms,我有一个在我们的软件(VB.NET)中运行的自定义通知。通知将在新线程中打开,因此当通知淡入或淡出时,用户仍可以与软件交互 我希望用户能够单击通知并在主线程上打开表单。当我使用普通的Form.Show()方法时,它会在通知所在的线程上打开,然后在通知关闭时关闭 如何让不同的线程在主线程上执行sub 我的代码正在更新 这将启动通知 Public Sub StartNotificationThread(sender, e) 'started from main thread Try
Form.Show()方法时,它会在通知所在的线程上打开,然后在通知关闭时关闭
如何让不同的线程在主线程上执行sub
我的代码正在更新
这将启动通知
Public Sub StartNotificationThread(sender, e) 'started from main thread
Try
thread2 = New System.Threading.Thread(AddressOf Notificaition)'my notification thread
thread2.SetApartmentState(ApartmentState.STA)
thread2.Start()
Catch ex As Exception
error_form = Me.ToString
Email_Error(sender, ex)
End Try
End Sub
我想单击我的通知并在主线程上执行类似的操作
Public Sub NotificationClicked()'launched from notification thread
Form1.show 'Do stuff in main thread
Me.Close()
End Sub
这为您提供了一个开始的想法:
(但我要说的是,最好不要只是问,而是展示你想做什么——说编码——或者通过几行代码给出你想法的一个小场景)
然后,您可以按如下方式从每个线程调用:
Dim T As Threading.Thread = New Threading.Thread(Sub()
MainForm.CallMeFromEveryWhere()
End Sub)
T.Start()
Dim T As Threading.Thread = New Threading.Thread(Sub()
Invoke(Sub()
MainThreadForm.Show()
End Sub)
End Sub)
T.Start()
要显示主线程形式,您可以使用以下方法:
Dim T As Threading.Thread = New Threading.Thread(Sub()
MainForm.CallMeFromEveryWhere()
End Sub)
T.Start()
Dim T As Threading.Thread = New Threading.Thread(Sub()
Invoke(Sub()
MainThreadForm.Show()
End Sub)
End Sub)
T.Start()
如果要封送对表单中UI线程的方法调用,通常会对表单或其某个控件调用Invoke
,以调用拥有该表单的线程上的方法。在本例中,这不是一个选项,因为表单不属于UI线程
在表单以外的类中,通常使用SynchronizationContext
类,在创建对象时获取当前值,然后在次线程上执行的代码中使用该值。这是你应该在这里做的,但有一个变化
不同之处在于,您无法在表单本身中获取SynchronizationContext.Current
,因为它是在辅助线程上创建的。您需要首先在调用表单中,在UI线程上执行的代码中获取SynchronizationContext.Current
。然后,当您在辅助线程上执行代码以创建和显示第二个表单时,您将传入该SynchornizationContext
实例,然后使用它在UI线程上执行代码。下面是一个简单的例子:
主要(启动)表格:
导入系统线程
公开课表格1
'UI线程的SynchronizationContext。
私有uiContext作为SynchronizationContext=SynchronizationContext.Current
私有子按钮1\u单击(发送者作为对象,e作为事件参数)处理按钮1。单击
'在辅助线程上显示新的Form2实例。
调用新线程(Sub()调用新Form2(uiContext).ShowDialog()).Start()函数
端接头
末级
中学表格:
导入系统线程
公开课表格2
'UI线程的SynchronizationContext。
作为SynchronizationContext的专用uiContext
公共子新建(uiContext作为SynchronizationContext)
'设计器需要此调用。
初始化组件()
'在InitializeComponent()调用之后添加任何初始化。
Me.uiContext=uiContext
端接头
私有子按钮1\u单击(发送者作为对象,e作为事件参数)处理按钮1。单击
'在Form1的默认实例上显示文本。
'由于打开的Form1实例不属于当前线程,因此不会看到此文本。
Form1.Label1.Text=Date.Now.ToString()
端接头
私有子按钮2\u单击(发送者作为对象,e作为事件参数)处理按钮2。单击
'在UI线程上显示新的Form3实例。
uiContext.Send(子(状态)调用New Form3().Show(),无)
关闭()
端接头
末级
第三级:
公共类表单3
私有子按钮1\u单击(发送者作为对象,e作为事件参数)处理按钮1。单击
'在Form1的默认实例上显示文本。
'将看到此文本,因为打开的Form1实例属于当前线程。
Form1.Label1.Text=Date.Now.ToString()
端接头
末级
主窗体需要一个按钮
和一个标签
,次窗体需要两个按钮
,三级窗体需要一个按钮
单击主窗体上的按钮
时,它将在次线程上创建和显示次窗体,并将UI线程的SynchrinizationContext
传递给它。您可以向自己证明辅助窗体由辅助线程拥有,因为它是通过调用ShowDialog
显示的,但您仍然可以访问主窗体。此外,您可以单击第一个按钮
,主窗体上的标签将不受影响。这是因为代码是在辅助线程上执行的,因此该线程的Form1
的默认实例不是显示的实例
然后,您可以单击辅助窗体上的第二个按钮
,在UI线程上创建和显示第三个窗体,并关闭辅助窗体。通过单击按钮
并查看主表单更新上的标签
,您可以向自己证明它属于UI线程。这表明当前线程的默认实例是当前显示的实例,因此当前线程必须是UI线程。您好,谢谢您的帮助,但它似乎仍在另一个线程的子线程上运行。我将用更多的代码更新我的主要问题。因此,您可以将这两个方法放在主线程形式中,或者您可以从通知控件/直接从中执行,正如las代码所示:(今天运气不太好。当我从通知线程Dim T作为Threading.thread=New Threading.thread(Sub()运行此代码时)从abo调用(Sub()About.Show()End Sub)End Sub)T.Start()