SerialPort reading cause error because of not owning thread
.net, serial-port, vb.net, wpf
Solution
WELCOME TO THE MAGICAL WORLD OF MULTITHREADING!!!
What's happening is that all of your UI elements (class instances) can only be accessed/updated by the UI thread. I won't go into the details about this thread affinity, but its an important subject and you should check it out.
The event where data is coming in on the serial port is happening on a different thread than the UI thread. The UI thread has a message pump that handles windows messages (like mouse clicks etc). Your serial port doesn't send off windows messages. When data comes in on the serial port a completely different thread from your UI thread is used to process that message.
So, within your application, the mSerialPort_DataReceived method is executing in a different thread than your UI thread. You can use the Threads debugging window to verify this.
When you attempt to update your UI, you are trying to modify a control with thread affinity for the UI thread from a different thread, which throws the exception you've seen.
TL;DR: You are trying to modify a UI element outside of the UI thread. Use
txtSerialOutput.Dispatcher.Invoke
to run your update on the UI thread. There's an example here on how to do thisin the community content of this page.
The Dispatcher will Invoke your method on the UI thread (it sends a windows message to the UI saying "Hai guize, run this method kthx"), and your method can then safely update the UI from the UI thread.
Problem
I have a simple WPF windows application trying to read a serial port with the `System.IO.Ports.SerialPort`. When I try to read the incoming data in the `DataReceived` event, I get an exception saying that I don't have access to the thread. How do I solve it? I have this in the WPF window class: ``` 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 ``` When the `DataReceived` event triggers, I get the following exception on `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) ```