【问题标题】:Use async/ await or something else使用 async/await 或其他东西
【发布时间】:2016-09-12 08:57:41
【问题描述】:

我正在编写一个与我设计的一些控制硬件进行通信的程序。硬件正在驱动电机,我尝试用它做的第一件事是初始化电机。 硬件是通信控制的,所以我只需通过 USB 向硬件发送一条消息即可。 要初始化电机,我必须发送 2 条消息;在我发送第一个之后,它会将电机移向传感器,当它到达它时它会停止并向我发送一条消息,告诉我它已经停止,此时我向它发送另一条消息,告诉它驱动电机相反的方向非常缓慢,直到它从传感器中出来。

我所有的通讯接收都在 SerialPort DataReceived 事件中。我可以等待相关消息然后发送第二条消息的最佳方式是什么?目前我只是使用 bool 类型的属性,在初始化之前我将其设置为 true,然后在我的事件处理程序中,如果我收到消息告诉我电机已停止并且 bool 为真,我设置 bool为假并发送第二条消息。虽然这可行,但我在想可能可以使用异步和等待?总的来说,这可能会更有效率吗?还是我可以采取另一种更好的方法? 任何反馈/指导将不胜感激!

【问题讨论】:

  • 距离不够近,不能被称为重复,但您可能想看看我为 for a similar answer 设计的一个类,该类将对 SeralPort 的请求排队并异步等待响应。跨度>
  • 谢谢你,非常有用!我会看看我是否可以调整和实现类似的东西,但我不能使用你提出的确切答案,因为我确实需要事件来处理消息的接收。

标签: c# asynchronous serial-port async-await


【解决方案1】:

在我看来,async-await 的好处并不在于它可以让调用者保持响应,而是你的代码看起来更简单,就好像它不是 async-await 一样。

还可以使用 Tasks 和 ContinueWith 语句,或者使用 Backgroundworker 或其他方法创建线程来保持调用者响应。但是如果你使用异步等待,你就不必记住你的进度状态,你现在可以通过设置布尔值来完成。

您的代码如下所示:

public Task InitializeAsync(...)
{
    await Send1stMessageAsync();
    await Send2ndMessageAsync();
}

In this article Eric Lippert explained async-await using a kitchen metaphor。发生的情况是,您的线程将尽一切努力发送第一条消息,直到它不能再做任何事情,只能等待回复。然后将控制权交给没有等待的第一个调用者。如果您不等待,那就是您,例如,如果您有以下代码:

public Task InitializeAsync(...)
{
    var task1stMessage = Send1stMessageAsync();
    // this thread will do everything inside Send1stMessageAsync until it sees an await.
    // it then returns control to this function until there is an await here:
    DoSomeThingElse();
    // after a while you don't have anything else to do, 
    // so you wait until your first messages has been sent
    // and the reply received:
    await task1stMessage;
    // control is given back to your caller who might have something
    // useful to do  until he awaits and control is given to his caller etc.
    // when the await inside Send1stMessageAync is completed, the next statements inside
    // Send1stMessageAsync are executed until the next await, or until the function completes.

    var task2ndMessage = Send2ndMessageAsync();
    DoSomethingUseful();
    await task2ndMessage;
}

您写道,您使用事件来通知您的线程已收到数据。尽管使您的 Send1stMessageAsync 成为异步函数并不难,但您不必重新发明轮子。考虑使用像 SerialPortStream 这样的 nuget 包来获取发送消息并等待回复的异步函数。

【讨论】:

    【解决方案2】:

    如果您正在等待某些事情发生并且您没有事件处理程序可供您使用,那么使用 async/await 模式是个好主意

    async Task WaitForCompletion()
    {
        await Task.Run(()=>
        {
            while(!theBoolVar)
                Thread.Sleep(1000);
        });
    }
    

    然后就在你的代码中使用

    await WaitForCompletion();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-22
      • 1970-01-01
      • 1970-01-01
      • 2018-02-12
      • 1970-01-01
      • 2017-03-12
      相关资源
      最近更新 更多