awe*_*awe 2 .net vb.net wpf serial-port
我有一个简单的WPF Windows应用程序试图读取串口System.IO.Ports.SerialPort.
当我尝试读取DataReceived事件中的传入数据时,我得到一个异常,说我无法访问该线程.我该如何解决?
我在WPF窗口类中有这个:
Public WithEvents mSerialPort As New SerialPort()
Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnConnect.Click
With mSerialPort
If .IsOpen Then
.Close()
End If
.BaudRate = 4800
.PortName = SerialPort.GetPortNames()(0)
.Parity = Parity.None
.DataBits = 8
.StopBits = StopBits.One
.NewLine = vbCrLf
.Open()
End With
End Sub
Private Sub mSerialPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles mSerialPort.DataReceived
If e.EventType = SerialData.Chars Then
txtSerialOutput.Text += mSerialPort.ReadExisting()
End If
End Sub
Protected Overrides Sub Finalize()
If mSerialPort.IsOpen Then
mSerialPort.Close()
End If
mSerialPort.Dispose()
mSerialPort = Nothing
MyBase.Finalize()
End Sub
Run Code Online (Sandbox Code Playgroud)
当DataReceived事件触发时,我得到以下异常mSerialPort.ReadExisting():
System.InvalidOperationException was unhandled
Message="The calling thread cannot access this object because a different thread owns it."
Source="WindowsBase"
StackTrace:
at System.Windows.Threading.Dispatcher.VerifyAccess() at System.Windows.Threading.DispatcherObject.VerifyAccess() at System.Windows.DependencyObject.GetValue(DependencyProperty dp) at System.Windows.Controls.TextBox.get_Text() at Serial.Serial.mSerialPort_DataReceived(Object sender, SerialDataReceivedEventArgs e) in D:\SubVersion\VisionLite\Serial\Serial.xaml.vb:line 24 at System.IO.Ports.SerialPort.CatchReceivedEvents(Object src, SerialDataReceivedEventArgs e) at System.IO.Ports.SerialStream.EventLoopRunner.CallReceiveEvents(Object state) at System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack) at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)
Run Code Online (Sandbox Code Playgroud)
小智 7
欢迎来到多元化的神奇世界!
发生的事情是,所有UI元素(类实例)只能由UI线程访问/更新.我不会详细介绍这个线程关联,但它是一个重要的主题,你应该检查一下.
数据进入串行端口的事件发生在与UI线程不同的线程上.UI线程有一个消息泵来处理Windows消息(如鼠标点击等).您的串行端口不会发送Windows消息.当数据进入串行端口时,将使用与UI线程完全不同的线程来处理该消息.
因此,在您的应用程序中,mSerialPort_DataReceived方法在与您的UI线程不同的线程中执行.您可以使用"线程"调试窗口来验证这一点.
当您尝试更新UI时,您尝试从另一个线程修改具有线程关联性的UI线程控件,这会引发您看到的异常.
TL; DR:您正在尝试修改UI线程之外的UI元素.使用
txtSerialOutput.Dispatcher.Invoke
Run Code Online (Sandbox Code Playgroud)
在UI线程上运行更新. 这里有一个关于如何在此页面的社区内容中执行此操作的示例.
Dispatcher将在UI线程上调用您的方法(它向UI发送一条窗口消息,说"Hai guize,运行此方法kthx"),然后您的方法可以安全地从UI线程更新UI.