我正在编写一个将数据传输到USB HID类设备的WinForms应用程序 . 我的应用程序使用优秀的Generic HID库v6.0,可以找到here . 简而言之,当我需要将数据写入设备时,这是被调用的代码:
private async void RequestToSendOutputReport(List<byte[]> byteArrays)
{
foreach (byte[] b in byteArrays)
{
while (condition)
{
// we'll typically execute this code many times until the condition is no longer met
Task t = SendOutputReportViaInterruptTransfer();
await t;
}
// read some data from device; we need to wait for this to return
RequestToGetInputReport();
}
}
当我的代码退出while循环时,我需要从设备中读取一些数据 . 但是,设备无法立即响应,因此我需要等待此呼叫返回才能继续 . 因为它目前存在,RequestToGetInputReport()声明如下:
private async void RequestToGetInputReport()
{
// lots of code prior to this
int bytesRead = await GetInputReportViaInterruptTransfer();
}
对于它的 Value ,GetInputReportViaInterruptTransfer()的声明如下所示:
internal async Task<int> GetInputReportViaInterruptTransfer()
不幸的是,我不熟悉.NET 4.5中新的异步/等待技术的工作原理 . 我之前对await关键字进行了一些阅读,这让我觉得在RequestToGetInputReport()内部调用GetInputReportViaInterruptTransfer()会等待(也许它会这样做?)但它似乎不是对RequestToGetInputReport()的调用本身正在等待,因为我似乎几乎立即重新进入while循环?
任何人都可以澄清我所看到的行为吗?
4 回答
等待AsynMethod直到完成任务的最佳解决方案
以下代码段显示了一种确保等待方法在返回调用方之前完成的方法 . 但是,我不会说这是好习惯 . 如果您不这么认为,请用解释编辑我的答案 .
避免
async void
. 让您的方法返回Task而不是void
. 然后你可以await他们 .像这样:
关于
async
和await
最重要的一点是await
不等待相关的调用完成 .await
的作用是在操作已经完成时立即和同步返回操作的结果,或者如果没有,则调度继续执行async
方法的剩余部分,然后将控制返回给调用者 . 异步操作完成后,将执行计划的完成 .问题 Headers 中特定问题的答案是通过调用适当的
Wait
方法来阻止async
方法的返回值(应该是Task
或Task<T>
类型):在此代码段中,
CallGetFooAsyncAndWaitOnResult
是异步方法GetFooAsync
的同步包装器 . 但是,大多数情况下应避免使用此模式,因为它将在异步操作期间阻塞整个线程池线程 . 这是对API公开的各种异步机制的低效使用,它们努力提供它们 ."await" doesn't wait for the completion of call的答案有几个更详细的解释 .
与此同时,@ Stete Cleary关于
async void
的指导持有 . 其他很好的解释可以在http://www.tonicodes.net/blog/why-you-should-almost-never-write-void-asynchronous-methods/和http://www.jaylee.org/post/2012/07/08/c-sharp-async-tips-and-tricks-part-2-async-void.aspx找到 .