簡體   English   中英

如何等待異步方法完成?

[英]How to wait for async method to complete?

我正在編寫一個將數據傳輸到 USB HID 類設備的 WinForms 應用程序。 我的應用程序使用了優秀的通用 HID 庫 v6.0,可以在這里找到。 簡而言之,當我需要將數據寫入設備時,這是調用的代碼:

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

值得一提的是,GetInputReportViaInterruptTransfer() 的聲明如下所示:

internal async Task<int> GetInputReportViaInterruptTransfer()

不幸的是,我不太熟悉 .NET 4.5 中新的 async/await 技術的工作原理。 我之前閱讀了一些關於 await 關鍵字的內容,這給我的印象是在 RequestToGetInputReport() 中調用 GetInputReportViaInterruptTransfer() 會等待(也許它會等待?)但它似乎不像是對 RequestToGetInputReport() 的調用本身正在等待,因為我似乎幾乎立即重新進入 while 循環?

任何人都可以澄清我所看到的行為嗎?

關於asyncawait最重要的事情是await等待關聯的調用完成。 await所做的是在操作已經完成時立即並同步地返回操作的結果,或者,如果尚未完成,則安排繼續執行async方法的其余部分,然后將控制權返回給調用者。 異步操作完成后,將執行計划完成。

問題標題中特定問題的答案是通過調用適當的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”處的答案不等待調用完成,對這些關鍵字有幾個更詳細的解釋。

同時,@Stephen Cleary 關於async void的指導也成立。 關於原因的其他很好的解釋可以在http://www.tonicodes.net/blog/why-you-should-almost-never-write-void-asynchronous-methods/https://jaylee.org/archive/找到2012/07/08/c-sharp-async-tips-and-tricks-part-2-async-void.html

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

等待 AsynMethod 直到完成任務的最佳解決方案是

var result = Task.Run(async() => await yourAsyncMethod()).Result;

只需放置 Wait() 等待任務完成

GetInputReportViaInterruptTransfer().Wait();

這是使用標志的解決方法:

//outside your event or method, but inside your class
private bool IsExecuted = false;

private async Task MethodA()
{

//Do Stuff Here

IsExecuted = true;
}

.
.
.

//Inside your event or method

{
await MethodA();

while (!isExecuted) Thread.Sleep(200); // <-------

await MethodB();
}

以下代碼段顯示了一種確保等待的方法在返回調用者之前完成的方法。 但是,我不會說這是一種很好的做法。 如果您不這么認為,請編輯我的答案並解釋。

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

await AnAsyncMethodThatCompletes();
Console.WriteLine("AnAsyncMethodThatCompletes() completed.")

實際上我發現這對返回 IAsyncAction 的函數更有幫助。

            var task = asyncFunction();
            while (task.Status == AsyncStatus.Completed) ;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM