2017-01-15 37 views
1

我正在尝试创建一个初始化树莓和arduino之间的串行连接的类。课程还应能够读写已建立的串行连接。为什么我的异步方法不等待“serialPort = await SerialDevice.FromIdAsync()”?

我使用的代码来自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); 
} 

我在serial.appxmanifest中添加了serialcommunication功能。

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

到目前为止一切正常。树莓在另一端成功发送和接收来自Arduino的消息。

现在我试着单独做这些步骤。首先初始化串行连接,以便在应用程序需要时使用读取和写入功能。

的MainPage

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

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

SerialController

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()); 
     } 
    } 
} 

此代码不会等待一个串口,dataWriter和DataReader初始化。所以他们永远不会被分配到。

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

所有帮助表示赞赏。 在此先感谢!

回答

10

你的所有async方法返回void - 这意味着他们开始执行,并且调用的代码具有等待,直到它继续前实际完成没有简单的方法。只要您使用await表达的东西,还没有完成,异步方法将返回给调用者,已预约的延续,当awaitable完成将执行。就你而言,你只是继续下一个陈述。

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

在进行任何详细的更改之前,您应该仔细阅读有关asyncawait所做的更多操作 - 尝试在不理解它们的情况下使用它们是导致进一步问题的秘诀。

+0

感谢您的回复。这是我第一次需要处理异步,并期待完全不同的行为。我通过使InitSerial()成为任务来解决问题,并等待任务的完成。 – MKFreebird

1

这是你的构造:

public SerialController() 
{ 
    InitSerial(); 
} 

它将调用具有有几个等待(S)在他们InitSerial()方法。构造函数立即返回,没有做任何需要的事情。然后调用这些方法:

serial.Write(); 
serial.Read(); 

但是,这些方法依赖于每一行代码已经在InitSerial方法内执行,但显然他们没有。

解决这个问题的一种方法是使InitSerial不是私有的(内部或公共的),并让它返回Task。当你调用它时,你需要等待它,以便它已经被执行完成。之后,您可以拨打serial.Write()Serial.Read()。您应该避免async void。它们仅用于事件处理。其他方法返回TaskTask<T>