I have a problem while doing the translation of C # code to VB.NET on the UWP platform doing a Serial UART Test Example made available by the Microsoft website. The program in C # is working perfectly, but when I try to run in VB.NET, the moment I try to connect the port in RaspBerry Pi 3, the variable "serialPort" goes invalid and returns, like the image here worthless SerialPort.
I make the source code available here in C # and VB.NET, to compare if something is missing (probably yes) at the time the code was translated.
This image is the C # serialPort with value.
C # EXAMPLE
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Collections.ObjectModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;
using Windows.Storage.Streams;
using System.Threading;
using System.Threading.Tasks;
namespace SerialSample
{
public sealed partial class MainPage : Page
{
/// <summary>
/// Private variables
/// </summary>
private SerialDevice serialPort = null;
DataWriter dataWriteObject = null;
DataReader dataReaderObject = null;
private ObservableCollection<DeviceInformation> listOfDevices;
private CancellationTokenSource ReadCancellationTokenSource;
public MainPage()
{
this.InitializeComponent();
comPortInput.IsEnabled = false;
sendTextButton.IsEnabled = false;
listOfDevices = new ObservableCollection<DeviceInformation>();
ListAvailablePorts();
}
/// <summary>
/// ListAvailablePorts
/// - Use SerialDevice.GetDeviceSelector to enumerate all serial devices
/// - Attaches the DeviceInformation to the ListBox source so that DeviceIds are displayed
/// </summary>
private async void ListAvailablePorts()
{
try
{
string aqs = SerialDevice.GetDeviceSelector();
var dis = await DeviceInformation.FindAllAsync(aqs);
status.Text = "Select a device and connect";
for (int i = 0; i < dis.Count; i++)
{
listOfDevices.Add(dis[i]);
}
DeviceListSource.Source = listOfDevices;
comPortInput.IsEnabled = true;
ConnectDevices.SelectedIndex = -1;
}
catch (Exception ex)
{
status.Text = ex.Message;
}
}
/// <summary>
/// comPortInput_Click: Action to take when 'Connect' button is clicked
/// - Get the selected device index and use Id to create the SerialDevice object
/// - Configure default settings for the serial port
/// - Create the ReadCancellationTokenSource token
/// - Start listening on the serial port input
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void comPortInput_Click(object sender, RoutedEventArgs e)
{
var selection = ConnectDevices.SelectedItems;
if (selection.Count <= 0)
{
status.Text = "Select a device and connect";
return;
}
DeviceInformation entry = (DeviceInformation)selection[0];
try
{
serialPort = await SerialDevice.FromIdAsync(entry.Id);
if (serialPort == null) return;
// Disable the 'Connect' button
comPortInput.IsEnabled = false;
// Configure serial settings
serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
serialPort.BaudRate = 9600;
serialPort.Parity = SerialParity.None;
serialPort.StopBits = SerialStopBitCount.One;
serialPort.DataBits = 8;
serialPort.Handshake = SerialHandshake.None;
// Display configured settings
status.Text = "Serial port configured successfully: ";
status.Text += serialPort.BaudRate + "-";
status.Text += serialPort.DataBits + "-";
status.Text += serialPort.Parity.ToString() + "-";
status.Text += serialPort.StopBits;
// Set the RcvdText field to invoke the TextChanged callback
// The callback launches an async Read task to wait for data
rcvdText.Text = "Waiting for data...";
// Create cancellation token object to close I/O operations when closing the device
ReadCancellationTokenSource = new CancellationTokenSource();
// Enable 'WRITE' button to allow sending data
sendTextButton.IsEnabled = true;
Listen();
}
catch (Exception ex)
{
status.Text = ex.Message;
comPortInput.IsEnabled = true;
sendTextButton.IsEnabled = false;
}
}
/// <summary>
/// sendTextButton_Click: Action to take when 'WRITE' button is clicked
/// - Create a DataWriter object with the OutputStream of the SerialDevice
/// - Create an async task that performs the write operation
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void sendTextButton_Click(object sender, RoutedEventArgs e)
{
try
{
if (serialPort != null)
{
// Create the DataWriter object and attach to OutputStream
dataWriteObject = new DataWriter(serialPort.OutputStream);
//Launch the WriteAsync task to perform the write
await WriteAsync();
}
else
{
status.Text = "Select a device and connect";
}
}
catch (Exception ex)
{
status.Text = "sendTextButton_Click: " + ex.Message;
}
finally
{
// Cleanup once complete
if (dataWriteObject != null)
{
dataWriteObject.DetachStream();
dataWriteObject = null;
}
}
}
/// <summary>
/// WriteAsync: Task that asynchronously writes data from the input text box 'sendText' to the OutputStream
/// </summary>
/// <returns></returns>
private async Task WriteAsync()
{
Task<UInt32> storeAsyncTask;
if (sendText.Text.Length != 0)
{
// Load the text from the sendText input text box to the dataWriter object
dataWriteObject.WriteString(sendText.Text);
// Launch an async task to complete the write operation
storeAsyncTask = dataWriteObject.StoreAsync().AsTask();
UInt32 bytesWritten = await storeAsyncTask;
if (bytesWritten > 0)
{
status.Text = sendText.Text + ", ";
status.Text += "bytes written successfully!";
}
sendText.Text = "";
}
else
{
status.Text = "Enter the text you want to write and then click on 'WRITE'";
}
}
/// <summary>
/// - Create a DataReader object
/// - Create an async task to read from the SerialDevice InputStream
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void Listen()
{
try
{
if (serialPort != null)
{
dataReaderObject = new DataReader(serialPort.InputStream);
// keep reading the serial input
while (true)
{
await ReadAsync(ReadCancellationTokenSource.Token);
}
}
}
catch (TaskCanceledException tce)
{
status.Text = "Reading task was cancelled, closing device and cleaning up";
CloseDevice();
}
catch (Exception ex)
{
status.Text = ex.Message;
}
finally
{
// Cleanup once complete
if (dataReaderObject != null)
{
dataReaderObject.DetachStream();
dataReaderObject = null;
}
}
}
/// <summary>
/// ReadAsync: Task that waits on data and reads asynchronously from the serial device InputStream
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private async Task ReadAsync(CancellationToken cancellationToken)
{
Task<UInt32> loadAsyncTask;
uint ReadBufferLength = 1024;
// If task cancellation was requested, comply
cancellationToken.ThrowIfCancellationRequested();
// Set InputStreamOptions to complete the asynchronous read operation when one or more bytes is available
dataReaderObject.InputStreamOptions = InputStreamOptions.Partial;
using (var childCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
{
// Create a task object to wait for data on the serialPort.InputStream
loadAsyncTask = dataReaderObject.LoadAsync(ReadBufferLength).AsTask(childCancellationTokenSource.Token);
// Launch the task and wait
UInt32 bytesRead = await loadAsyncTask;
if (bytesRead > 0)
{
rcvdText.Text = dataReaderObject.ReadString(bytesRead);
status.Text = "bytes read successfully!";
}
}
}
/// <summary>
/// CancelReadTask:
/// - Uses the ReadCancellationTokenSource to cancel read operations
/// </summary>
private void CancelReadTask()
{
if (ReadCancellationTokenSource != null)
{
if (!ReadCancellationTokenSource.IsCancellationRequested)
{
ReadCancellationTokenSource.Cancel();
}
}
}
/// <summary>
/// CloseDevice:
/// - Disposes SerialDevice object
/// - Clears the enumerated device Id list
/// </summary>
private void CloseDevice()
{
if (serialPort != null)
{
serialPort.Dispose();
}
serialPort = null;
comPortInput.IsEnabled = true;
sendTextButton.IsEnabled = false;
rcvdText.Text = "";
listOfDevices.Clear();
}
/// <summary>
/// closeDevice_Click: Action to take when 'Disconnect and Refresh List' is clicked on
/// - Cancel all read operations
/// - Close and dispose the SerialDevice object
/// - Enumerate connected devices
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void closeDevice_Click(object sender, RoutedEventArgs e)
{
try
{
status.Text = "";
CancelReadTask();
CloseDevice();
ListAvailablePorts();
}
catch (Exception ex)
{
status.Text = ex.Message;
}
}
}
}
VB.NET EXAMPLE
Imports System
Imports System.Collections.ObjectModel
Imports Windows.UI.Xaml
Imports Windows.UI.Xaml.Controls
Imports Windows.Devices.Enumeration
Imports Windows.Devices.SerialCommunication
Imports Windows.Storage.Streams
Imports System.Threading
Imports System.Threading.Tasks
Public NotInheritable Class MainPage
Inherits Page
''' <summary>
''' Private variables
''' </summary>
Private serialPort As SerialDevice = Nothing
Private dataWriteObject As DataWriter = Nothing
Private dataReaderObject As DataReader = Nothing
Private listOfDevices As ObservableCollection(Of DeviceInformation)
Private ReadCancellationTokenSource As CancellationTokenSource
Public Sub New()
MyBase.New
Me.InitializeComponent
comPortInput.IsEnabled = False
sendTextButton.IsEnabled = False
Me.listOfDevices = New ObservableCollection(Of DeviceInformation)
Me.ListAvailablePorts()
End Sub
''' <summary>
''' ListAvailablePorts
''' - Use SerialDevice.GetDeviceSelector to enumerate all serial devices
''' - Attaches the DeviceInformation to the ListBox source so that DeviceIds are displayed
''' </summary>
Private Async Sub ListAvailablePorts()
Try
Dim aqs As String = SerialDevice.GetDeviceSelector
Dim dis = Await DeviceInformation.FindAllAsync(aqs)
status.Text = "Select a device and connect"
Dim i As Integer = 0
Do While (i < dis.Count)
Me.listOfDevices.Add(dis(i))
i = (i + 1)
Loop
DeviceListSource.Source = Me.listOfDevices
comPortInput.IsEnabled = True
ConnectDevices.SelectedIndex = -1
Catch ex As Exception
status.Text = ex.Message
End Try
End Sub
''' <summary>
''' comPortInput_Click: Action to take when 'Connect' button is clicked
''' - Get the selected device index and use Id to create the SerialDevice object
''' - Configure default settings for the serial port
''' - Create the ReadCancellationTokenSource token
''' - Start listening on the serial port input
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Async Sub comPortInput_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim selection = ConnectDevices.SelectedItems
If (selection.Count <= 0) Then
status.Text = "Select a device and connect"
Return
End If
Dim entry As DeviceInformation = CType(selection(0), DeviceInformation)
Try
serialPort = Await SerialDevice.FromIdAsync(entry.Id)
If (serialPort Is Nothing) Then
Return
End If
' Disable the 'Connect' button
comPortInput.IsEnabled = False
' Configure serial settings
Me.serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000)
Me.serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000)
Me.serialPort.BaudRate = 9600
Me.serialPort.Parity = SerialParity.None
Me.serialPort.StopBits = SerialStopBitCount.One
Me.serialPort.DataBits = 8
Me.serialPort.Handshake = SerialHandshake.None
' Display configured settings
status.Text = "Serial port configured successfully: "
status.Text = (status.Text _
+ (Me.serialPort.BaudRate + "-"))
status.Text = (status.Text _
+ (Me.serialPort.DataBits + "-"))
status.Text = (status.Text _
+ (Me.serialPort.Parity.ToString + "-"))
status.Text = (status.Text + Me.serialPort.StopBits)
' Set the RcvdText field to invoke the TextChanged callback
' The callback launches an async Read task to wait for data
rcvdText.Text = "Waiting for data..."
' Create cancellation token object to close I/O operations when closing the device
Me.ReadCancellationTokenSource = New CancellationTokenSource
' Enable 'WRITE' button to allow sending data
sendTextButton.IsEnabled = True
Me.Listen()
Catch ex As Exception
status.Text = ex.Message
comPortInput.IsEnabled = True
sendTextButton.IsEnabled = False
End Try
End Sub
''' <summary>
''' sendTextButton_Click: Action to take when 'WRITE' button is clicked
''' - Create a DataWriter object with the OutputStream of the SerialDevice
''' - Create an async task that performs the write operation
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Async Sub sendTextButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Try
If (Not (Me.serialPort) Is Nothing) Then
' Create the DataWriter object and attach to OutputStream
Me.dataWriteObject = New DataWriter(Me.serialPort.OutputStream)
'Launch the WriteAsync task to perform the write
Await Me.WriteAsync()
Else
status.Text = "Select a device and connect"
End If
Catch ex As Exception
status.Text = ("sendTextButton_Click: " + ex.Message)
Finally
' Cleanup once complete
If (Not (Me.dataWriteObject) Is Nothing) Then
Me.dataWriteObject.DetachStream()
Me.dataWriteObject = Nothing
End If
End Try
End Sub
''' <summary>
''' WriteAsync: Task that asynchronously writes data from the input text box 'sendText' to the OutputStream
''' </summary>
''' <returns></returns>
Private Async Function WriteAsync() As Task
Dim storeAsyncTask As Task(Of UInt32)
If (sendText.Text.Length <> 0) Then
' Load the text from the sendText input text box to the dataWriter object
Me.dataWriteObject.WriteString(sendText.Text)
' Launch an async task to complete the write operation
storeAsyncTask = Me.dataWriteObject.StoreAsync.AsTask
Dim bytesWritten As UInt32 = Await storeAsyncTask
If (bytesWritten > 0) Then
status.Text = (sendText.Text + ", ")
status.Text = (status.Text + "bytes written successfully!")
End If
sendText.Text = ""
Else
status.Text = "Enter the text you want to write and then click on 'WRITE'"
End If
End Function
''' <summary>
''' - Create a DataReader object
''' - Create an async task to read from the SerialDevice InputStream
''' </summary>
Private Async Sub Listen()
Try
If (Not (Me.serialPort) Is Nothing) Then
Me.dataReaderObject = New DataReader(Me.serialPort.InputStream)
' keep reading the serial input
While True
Await Me.ReadAsync(Me.ReadCancellationTokenSource.Token)
End While
End If
Catch tce As TaskCanceledException
status.Text = "Reading task was cancelled, closing device and cleaning up"
Me.closeDevice()
Catch ex As Exception
status.Text = ex.Message
Finally
' Cleanup once complete
If (Not (Me.dataReaderObject) Is Nothing) Then
Me.dataReaderObject.DetachStream()
Me.dataReaderObject = Nothing
End If
End Try
End Sub
''' <summary>
''' ReadAsync: Task that waits on data and reads asynchronously from the serial device InputStream
''' </summary>
''' <param name="cancellationToken"></param>
''' <returns></returns>
Private Async Function ReadAsync(ByVal cancellationToken As CancellationToken) As Task
Dim loadAsyncTask As Task(Of UInt32)
Dim ReadBufferLength As UInteger = 1024
' If task cancellation was requested, comply
cancellationToken.ThrowIfCancellationRequested()
' Set InputStreamOptions to complete the asynchronous read operation when one or more bytes is available
Me.dataReaderObject.InputStreamOptions = InputStreamOptions.Partial
Dim childCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)
' Create a task object to wait for data on the serialPort.InputStream
loadAsyncTask = Me.dataReaderObject.LoadAsync(ReadBufferLength).AsTask(childCancellationTokenSource.Token)
' Launch the task and wait
Dim bytesRead As UInt32 = Await loadAsyncTask
If (bytesRead > 0) Then
rcvdText.Text = Me.dataReaderObject.ReadString(bytesRead)
status.Text = "bytes read successfully!"
End If
End Function
''' <summary>
''' CancelReadTask:
''' - Uses the ReadCancellationTokenSource to cancel read operations
''' </summary>
Private Sub CancelReadTask()
If (Not (Me.ReadCancellationTokenSource) Is Nothing) Then
If Not Me.ReadCancellationTokenSource.IsCancellationRequested Then
Me.ReadCancellationTokenSource.Cancel()
End If
End If
End Sub
''' <summary>
''' CloseDevice:
''' - Disposes SerialDevice object
''' - Clears the enumerated device Id list
''' </summary>
Private Sub CloseDevice()
If (Not (serialPort) Is Nothing) Then
Me.serialPort.Dispose()
End If
Me.serialPort = Nothing
comPortInput.IsEnabled = True
sendTextButton.IsEnabled = False
rcvdText.Text = ""
Me.listOfDevices.Clear()
End Sub
''' <summary>
''' closeDevice_Click: Action to take when 'Disconnect and Refresh List' is clicked on
''' - Cancel all read operations
''' - Close and dispose the SerialDevice object
''' - Enumerate connected devices
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub closeConnection_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Try
status.Text = ""
Me.CancelReadTask()
Me.CloseDevice()
Me.ListAvailablePorts()
Catch ex As Exception
status.Text = ex.Message
End Try
End Sub
End Class
In XAML Source, both are the same except for the 'Disconnect Button' with different names, but it does not affect my current problem, I've been standing in this part of the project for almost two weeks, and I really appreciate any help on how to solve that issue.