为什么我的功能不能连续运行?

时间:2019-01-15 10:47:09

标签: c# uwp serial-port

我正在尝试基于this示例实现串行读取器。

我尝试实现main函数以从串行读取并在主页的文本框中打印它。我必须读取带有24个字符和两个结尾行“ \ r \ n”的条形码,因此我将ReadBufferLength变量初始化为26(我不知道它是否正确)。连接的参数正确并且已建立连接。我想连续运行“监听”功能,以便在使用应用程序的任何时候都能接收数据,并始终打印文本框中接收到的数据。

我对mainpage.xaml.cs的代码是:

namespace App1
{

  public sealed partial class MainPage : Page
  {
    private CancellationTokenSource ReadCancellationTokenSource;
    private SerialDevice serialPort = null;
    DataReader dataReaderObject = null;

    public MainPage()
    {
        this.InitializeComponent();
    }

    private async void Page_Loaded(object sender, RoutedEventArgs e)
    {
        string qFilter = SerialDevice.GetDeviceSelector("COM3");
        DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(qFilter);

        if (devices.Any())
        {
            string deviceId = devices.First().Id;

            await OpenPort(deviceId);
        }

        ReadCancellationTokenSource = new CancellationTokenSource();

        while (true)
        {
            await Listen();
        }
    }

    private async Task OpenPort(string deviceId)
    {
        serialPort = await SerialDevice.FromIdAsync(deviceId);

        if (serialPort != null)
        {
            serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
            serialPort.BaudRate = 9600;
            serialPort.Parity = SerialParity.None;
            serialPort.StopBits = SerialStopBitCount.One;
            serialPort.DataBits = 8;
            txtStatus.Text = "Serial port configured successfully";
        }
    }

    private async Task Listen()
    {
        try
        {
            if (serialPort != null)
            {
                dataReaderObject = new DataReader(serialPort.InputStream);
                await ReadAsync(ReadCancellationTokenSource.Token);
            }
        }
        catch (Exception ex)
        {
            txtStatus.Text = ex.Message;
        }
        finally
        {
            if (dataReaderObject != null)    
            {
                dataReaderObject.DetachStream();
                dataReaderObject = null;
            }
        }
    }

    private async Task ReadAsync(CancellationToken cancellationToken)
    {
        Task<UInt32> loadAsyncTask;

        uint ReadBufferLength = 26;  

        dataReaderObject.InputStreamOptions = InputStreamOptions.Partial;

        loadAsyncTask = dataReaderObject.LoadAsync(ReadBufferLength).AsTask(cancellationToken);  

        UInt32 bytesRead = await loadAsyncTask;   

        if (bytesRead > 0)
        {
            string strFromPort = dataReaderObject.ReadString(bytesRead);
            txtPortData.Text = strFromPort;
            txtStatus.Text = "Read at " + DateTime.Now.ToString(System.Globalization.CultureInfo.CurrentUICulture.DateTimeFormat.LongTimePattern);
        }
    }

    private void CancelReadTask()
    {
        if (ReadCancellationTokenSource != null)
        {
            if (!ReadCancellationTokenSource.IsCancellationRequested)
            {
                ReadCancellationTokenSource.Cancel();
            }
        }
    }

    private void Page_Unloaded(object sender, RoutedEventArgs e)
    {
        CancelReadTask();
        if (serialPort != null)
        {
            serialPort.Dispose();
        }
        serialPort = null;
    }
  }
} 

当我运行该应用程序时,Listen函数仅被调用一次,如果我在串行端口上发送某些内容,我将永远不会收到数据。可能我错过了代码中的某些内容。

1 个答案:

答案 0 :(得分:1)

最后,我找到了解决方法...

我将System.IO.Ports包与两个不同的处理程序和一个对象收集器一起使用:

这进入SerialDevice类:

 private static ObservableCollection<string> ReadValues = null;

 public static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
 {
     SerialPort sp = (SerialPort)sender;
     string indata = sp.ReadLine();
     ReadValues.Add(indata);
 }

在主页中,我将这一行添加到page_loaded函数中:

mySerialDevice.GetList().CollectionChanged += NewFunctionHandler;

其中,GetList()是一个返回ReadValues变量的函数。而NewFunctionHandler类似于:

 public async void NewFunctionHandler(object sender, NotifyCollectionChangedEventArgs e)
 {
    if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
    {
        // do stuff
    }
 }

希望这对其他人有帮助...