簡體   English   中英

在Task <T>完成之前,正確暫停協程的方法

[英]Correct way to suspend coroutine until Task<T> is complete

我最近潛入Kotlin協同程序因為我使用了很多Google的庫,所以大部分工作都是在Task類中完成的

目前我正在使用此擴展來暫停協程

suspend fun <T> awaitTask(task: Task<T>): T = suspendCoroutine { continuation ->
    task.addOnCompleteListener { task ->
        if (task.isSuccessful) {
            continuation.resume(task.result)
        } else {
            continuation.resumeWithException(task.exception!!)
        }
    }
}

但最近我見過這樣的用法

suspend fun <T> awaitTask(task: Task<T>): T = suspendCoroutine { continuation ->
    try {
        val result = Tasks.await(task)
        continuation.resume(result)
    } catch (e: Exception) {
        continuation.resumeWithException(e)
    }
}

有什么區別,哪一個是正確的?

UPD:第二個例子不起作用,idk為什么

傳遞給suspendCoroutine { ... }的代碼塊不應該阻塞正在調用它的線程,允許協程被掛起。 這樣,實際線程可以用於其他任務。 這是一個關鍵功能,允許Kotlin協程擴展並在單個UI線程上運行多個協同程序。

第一個例子是正確的,因為它調用task.addOnCompleteListener (參見docs) (它只是添加一個監聽器並立即返回。這就是第一個正常工作的原因。

第二個示例使用Tasks.await(task) (請參閱docs)阻止調用它的線程,並且在任務完成之前不會返回,因此它不允許協程正確掛起。

您的第二個示例是更傳統的阻止功能。

在典型的Java多線程世界中,您使用類似的函數來阻塞線程,直到結果返回。

同樣在典型的Java中,有一種稱為Reactive programming的新范例,它允許您在結果返回之前避免阻塞線程。 您可以提供一個在結果到達時執行的第一類函數,而不是僅僅等待結果。 這樣,暫停時沒有留下線程; 相反,只有一個新事件附加到運行長操作的線程上,當操作完成時,該事件將觸發。

阻塞:

Thread one:  --* . . . ./---
Thread two:     \------*

反應:

Thread one: --*   (now free)
Thread two:    \-------*---

如果你研究反應式編程,你會發現更好的解釋,深入探討。

回到你的問題,這兩種看似相同的方式是Java范式轉變的結果。 當然,由於我們與協程在這里工作,我們不必擔心,阻斷問題沒有; 語言通過暫停而不是阻止來處理它。 因此,反應性編程的許多優點在語言層面上得到了解決。

然而 ,范式仍然有其優點,所以即使它不像其他地方那樣嚴格必要,看到人們繼續以這種模式工作也是有道理的。

暫無
暫無

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

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