使用 async/await 或其他东西

Posted

技术标签:

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

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

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

【问题讨论】:

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

【讨论】:

以上是关于使用 async/await 或其他东西的主要内容,如果未能解决你的问题,请参考以下文章

异步编程async/await

7张图,20分钟完全搞定async/await原理!(收藏)

使用 async/await 锁定资源

使用 async/await 仍然返回 undefined

async/await 的使用

async/await小知识点