c# - 为什么我的异步方法不等待 "serialPort = await SerialDevice.FromIdAsync()"?

标签 c# asynchronous raspberry-pi3 windows-10-iot-core

我正在尝试创建一个类来初始化树莓派和 arduino 之间的串行连接。该类还应该能够通过已建立的串行连接进行读写。

我使用的代码来自 microsoft developers website .

using Windows.Storage.Streams;
using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;

public async void Serial()
{
    /* Find the selector string for the serial device   */
    string aqs = SerialDevice.GetDeviceSelector("UART0");
    /* Find the serial device with our selector string  */
    var dis = await DeviceInformation.FindAllAsync(aqs);
    /* Create an serial device with our selected device */
    SerialDevice SerialPort = await SerialDevice.FromIdAsync(dis[0].Id);
    /* 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;

    /* Write a string out over serial */
    string txBuffer = "Hello Serial";
    DataWriter dataWriter = new DataWriter();
    dataWriter.WriteString(txBuffer);
    uint bytesWritten = await SerialPort.OutputStream.WriteAsync(dataWriter.DetachBuffer());

    /* Read data in from the serial port */
    const uint maxReadLength = 1024;
    DataReader dataReader = new DataReader(SerialPort.InputStream);
    uint bytesToRead = await dataReader.LoadAsync(maxReadLength);
    string rxBuffer = dataReader.ReadString(bytesToRead);
}

我将串行通信功能添加到 Package.appxmanifest。

<Capabilities>
  <DeviceCapability Name="serialcommunication">
    <Device Id="any">
      <Function Type="name:serialPort" />
    </Device>
  </DeviceCapability>
</Capabilities>

到目前为止一切正常。 Raspberry 成功地从另一端的 Arduino 发送和接收消息。

现在我尝试分别执行这些步骤。首先初始化串行连接,以便在应用程序需要时随时使用读写功能。

主页

namespace SerialUART
{
    public sealed partial class MainPage : Page
    {
        private SerialController serial = new SerialController();

        public MainPage()
        {
            this.InitializeComponent();
            serial.Write();
            serial.Read();
        }
    }
}

串行 Controller

using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;
using Windows.Storage.Streams;

namespace SerialUART
{
    class SerialController
    {
        private SerialDevice SerialPort;
        private DataWriter dataWriter;
        private DataReader dataReader;

        public SerialController()
        {
            InitSerial();
        }

        private async void InitSerial()
        {
            string aqs = SerialDevice.GetDeviceSelector("UART0");
            var dis = await DeviceInformation.FindAllAsync(aqs);
            SerialPort = await SerialDevice.FromIdAsync(dis[0].Id);    
            // The program does not wait here and executes Write()
            // after Write() the following code will be executed
            SerialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
            SerialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
            SerialPort.BaudRate = 9600;
            SerialPort.Parity = SerialParity.None;
            SerialPort.StopBits = SerialStopBitCount.One;
            SerialPort.DataBits = 8;
            dataWriter = new DataWriter();
            dataReader = new DataReader(SerialPort.InputStream);
        }

        public async void Read()
        {
            /* Read data in from the serial port */
            const uint maxReadLength = 1024;
            uint bytesToRead = await dataReader.LoadAsync(maxReadLength);
            string rxBuffer = dataReader.ReadString(bytesToRead);
            Debug.WriteLine(rxBuffer);
        }

        public async void Write()
        {
            /* Write a string out over serial */
            string txBuffer = "Hello Serial";
            dataWriter.WriteString(txBuffer);
            uint bytesWritten = await SerialPort.OutputStream.WriteAsync(dataWriter.DetachBuffer());
       }
    }
}

此代码不等待 serialPort、dataWriter 和 dataReader 初始化。所以他们永远不会被分配到。

谁能给我解释一下为什么它不等待串行连接?应该如何完成?

最佳答案

您所有的async 方法都返回void - 这意味着它们开始执行,并且调用代码没有简单的方法等待它真正执行在继续之前完成。一旦您在尚未完成的事情上使用 await 表达式,async 方法将返回给调用者,并安排了一个延续,该延续将在可等待完成时执行。在您的情况下,您只是继续下一个语句。

相反,您应该让您的异步方法返回 Task,并更改您的调用方法以等待异步方法完成后再继续。这很难做到优雅,因为在每种情况下,您都是从构造函数调用异步方法,而构造函数本身不能是异步的。您可能想考虑使用异步静态方法而不是在构造函数中执行工作,构造函数可以调用异步方法,等待它们,然后调用不执行任何实际工作的实际构造函数。

不过,在您进行任何详细更改之前,您真的应该阅读更多关于 asyncawait 的作用 - 尝试在不理解它们的情况下使用它们是一个秘诀进一步的问题。

关于c# - 为什么我的异步方法不等待 "serialPort = await SerialDevice.FromIdAsync()"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41664697/

相关文章:

c# - 在 OnMessageOptions 中使用 ExceptionReceived

c# - 将依赖项注入(inject) ASP.NET MVC 3 操作过滤器。这种方法有什么问题?

javascript - Node.js:REST 客户端在返回之前返回值

javascript - 如何使用 Axios 和 Typescript 等待响应?

Arch Arm 的交叉编译不会生成功能可执行文件

c# - 分析 Azure 辅助角色

c# - 使用 HttpClient 进行异步文件下载时的错误检查

video - 从 Youtube 输出流中保存 .mp4

azure - 使用自定义程序运行 Windows 10 Core 的 Raspberry Pi 3 显示划掉的 x

c# - 在 Azure 移动应用服务客户端中,如何设置 userId 以便 loginAsync 工作?