首页 文章

如何等待异步方法完成?

提问于
浏览
104

我正在编写一个将数据传输到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 回答

  • 37

    等待AsynMethod直到完成任务的最佳解决方案

    var result = Task.Run(async() => { return await yourAsyncMethod(); }).Result;
    
  • 103

    以下代码段显示了一种确保等待方法在返回调用方之前完成的方法 . 但是,我不会说这是好习惯 . 如果您不这么认为,请用解释编辑我的答案 .

    public async Task AnAsyncMethodThatCompletes()
    {
        await SomeAsyncMethod();
        DoSomeMoreStuff();
        await Task.Factory.StartNew(() => { }); // <-- This line here, at the end
    }
    
    await AnAsyncMethodThatCompletes();
    Console.WriteLine("AnAsyncMethodThatCompletes() completed.")
    
  • 175

    避免 async void . 让您的方法返回Task而不是 void . 然后你可以await他们 .

    像这样:

    private async Task 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
            await RequestToGetInputReport();
        }
    }
    
    private async Task RequestToGetInputReport()
    {
        // lots of code prior to this
        int bytesRead = await GetInputReportViaInterruptTransfer();
    }
    
  • -5

    关于 asyncawait 最重要的一点是 await 不等待相关的调用完成 . await 的作用是在操作已经完成时立即和同步返回操作的结果,或者如果没有,则调度继续执行 async 方法的剩余部分,然后将控制返回给调用者 . 异步操作完成后,将执行计划的完成 .

    问题 Headers 中特定问题的答案是通过调用适当的 Wait 方法来阻止 async 方法的返回值(应该是 TaskTask<T> 类型):

    public static async Task<Foo> GetFooAsync()
    {
        // Start asynchronous operation(s) and return associated task.
        ...
    }
    
    public static Foo CallGetFooAsyncAndWaitOnResult()
    {
        var task = GetFooAsync();
        task.Wait(); // Blocks current thread until GetFooAsync task completes
                     // For pedagogical use only: in general, don't do this!
        var result = task.Result;
        return result;
    }
    

    在此代码段中, 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找到 .

相关问题