gpt4 book ai didi

.net - 从不是在其上创建线程的线程访问的控件

转载 作者:行者123 更新时间:2023-12-03 13:18:46 26 4
gpt4 key购买 nike

我想基于网络更改事件更新表单(VB.NET)上的一些标签。在一个事件上,它可以完美运行,但另一个事件会引发此错误:

Cross-thread operation not valid: Control 'lblHostnameT' accessed from a thread other than the thread it was created on.



我正在编写一个用于网络诊断的小型应用程序。为了通知用户网络更改,我正在使用NetworkChange类。

在表单加载时,将创建事件处理程序:
AddHandler NetworkChange.NetworkAvailabilityChanged, AddressOf NetworkAvailabilityChanged
AddHandler NetworkChange.NetworkAddressChanged, AddressOf NetworkAddressChanged

这些是事件处理程序:
Private Sub NetworkAvailabilityChanged(sender As Object, e As NetworkAvailabilityEventArgs)
ResetStats()
niTray.ShowBalloonTip(5000)
End Sub

Private Sub NetworkAddressChanged(sender As Object, e As EventArgs)
ResetStats()
niTray.ShowBalloonTip(5000)
End Sub

这是ResetStats:
Private Sub ResetStats()
lblHostnameT.Text = "[na]"
lblIPT.Text = "[na]"
lblGWT.Text = "[na]"
lblDNST.Text = "[na]"
lblGWPingT.Text = "[na]"
lblDNSTestT.Text = "[na]"
lblDCPingT.Text = "[na]"
lblExtPingT.Text = "[na]"
GWPingSent = 0
GWPingReceived = 0
GWAverage = 0
DNSTestDone = 0
DNSTestOK = 0
DCPingSent = 0
DCPingReceived = 0
DCAverage = 0
ExtPingSent = 0
ExtPingReceived = 0
ExtAverage = 0
DCList.Clear()
DCList.Add("192.168.19.113")
DCList.Add("172.31.0.2")
DCList.Add("172.31.0.3")
DCList.Add("172.31.0.4")
ExtList.Clear()
ExtList.Add("www.google.com")
ExtList.Add("www.msn.com")
ExtList.Add("www.yahoo.com")
DNSTestList.Clear()
DNSTestList.Add("www.google.com")
DNSTestList.Add("www.msn.com")
DNSTestList.Add("www.yahoo.com")
DNSTaskList.Clear()
IPList.Clear()
GWList.Clear()
DNSList.Clear()
lblHostnameT.Text = My.Computer.Name

Dim nics() As NetworkInterface = NetworkInterface.GetAllNetworkInterfaces
Dim ipi As IPInterfaceProperties

For Each nic As NetworkInterface In nics
If (nic.OperationalStatus = OperationalStatus.Up) AndAlso (nic.NetworkInterfaceType <> NetworkInterfaceType.Loopback) Then
ipi = nic.GetIPProperties()
If (ipi IsNot Nothing) AndAlso (ipi.UnicastAddresses IsNot Nothing) AndAlso (ipi.UnicastAddresses.Count > 0) Then
For Each iip As IPAddressInformation In ipi.UnicastAddresses
If iip.Address.AddressFamily = Net.Sockets.AddressFamily.InterNetwork Then
IPList.Add(iip.Address.ToString & " (" & nic.Name & ")")
End If
Next
If (ipi.GatewayAddresses IsNot Nothing) AndAlso (ipi.GatewayAddresses.Count > 0) Then
For Each iip As GatewayIPAddressInformation In ipi.GatewayAddresses
If iip.Address.AddressFamily = Net.Sockets.AddressFamily.InterNetwork Then GWList.Add(iip.Address.ToString)
Next
End If
If (ipi.DnsAddresses IsNot Nothing) AndAlso (ipi.DnsAddresses.Count > 0) Then
For Each iip As Net.IPAddress In ipi.DnsAddresses
If iip.AddressFamily = Net.Sockets.AddressFamily.InterNetwork Then DNSList.Add(iip.ToString)
Next
End If
End If
End If
Next
lblIPT.Text = String.Join(", ", IPList.ToArray)
niTray.Text = "NetInfo" & vbCrLf & lblHostnameT.Text & vbCrLf & lblIPT.Text
lblGWT.Text = String.Join(", ", GWList.ToArray)
If GWList.Count > 1 Then
lblGWT.ForeColor = Color.Red
Else
lblGWT.ForeColor = Drawing.SystemColors.ControlText
End If
lblDNST.Text = String.Join(", ", DNSList.ToArray)
End Sub

当我更改一个NIC的连接性时(例如通过切换WiFi SSID),将触发NetworkAvailabilityChanged并更新UI。但是当我进行更改导致调用NetworkAddressChanged时(例如通过将以太网电缆插入笔记本电脑),应用程序崩溃并在ResetStats的第一行显示错误。怎么了

最佳答案

UI控件具有线程关联性;您只能从UI线程触摸它们。您的网络事件不是来自UI线程。解决方案是将UI工作反弹到UI线程。在C#中,这将类似于:

// not shown prep work to figure out what to do
// string newLabel = ...
this.Invoke((MethodInvoker) delegate {
// now we're on the UI thread
someControl.Text = newLabel;
// etc
});

很抱歉,我的VB不够强大,无法翻译。

如有疑问,您可以将整个内容弹回UI线程,但是对辅助线程进行预处理通常很有意义。但:

private void NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs args)
{
if (InvokeRequired)
{
Invoke((MethodInvoker)delegate { // jump to UI thread
NetworkAvailabilityChanged(sender, args);
});
}
else
{
// the real code
}
}

关于.net - 从不是在其上创建线程的线程访问的控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57266520/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com