Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Coroutine Kyuin

Avatar for uzzu uzzu
December 20, 2018

Coroutine Kyuin

社内勉強会「冬休み前にKotlinのCoroutinesを吸引したい人が集う会」資料

Avatar for uzzu

uzzu

December 20, 2018
Tweet

More Decks by uzzu

Other Decks in Technology

Transcript

  1. BTZODBXBJU $ class Program { static async ValueTask<int> DoSomething(int value)

    { await Task.Delay(1000); return value * value; } static async Task MainAsync(string[] args) { Console.WriteLine("Start task"); var result = await DoSomething(100); Console.WriteLine($"Result: {result}"); } static void Main(string[] args) => MainAsync(args).Wait(); }
  2. BTZODBXBJU $ class Program { static async ValueTask<int> DoSomething(int value)

    { await Task.Delay(1000); return value * value; } static async Task MainAsync(string[] args) { Console.WriteLine("Start task"); var result = await DoSomething(100); Console.WriteLine($"Result: {result}"); } static void Main(string[] args) => MainAsync(args).Wait(); }
  3. BTZODBXBJU $ class Program { static async ValueTask<int> DoSomething(int value)

    { await Task.Delay(1000); return value * value; } static async Task MainAsync(string[] args) { Console.WriteLine("Start task"); var result = await DoSomething(100); Console.WriteLine($"Result: {result}"); } static void Main(string[] args) => MainAsync(args).Wait(); }
  4. BTZODBXBJU &4 function sleep(milliSeconds) { return new Promise(resolve => setTimeout(resolve,

    milliSeconds)); } async function doSomething(value) { await sleep(1000); return value * value; } (async() => { console.log("Start task."); const result = await doSomething(100); console.log(`Result: ${result}`) })();
  5. BTZODBXBJU &4 function sleep(milliSeconds) { return new Promise(resolve => setTimeout(resolve,

    milliSeconds)); } async function doSomething(value) { await sleep(1000); return value * value; } (async() => { console.log("Start task."); const result = await doSomething(100); console.log(`Result: ${result}`) })();
  6. BTZODBXBJU &4 function sleep(milliSeconds) { return new Promise(resolve => setTimeout(resolve,

    milliSeconds)); } async function doSomething(value) { await sleep(1000); return value * value; } (async() => { console.log("Start task."); const result = await doSomething(100); console.log(`Result: ${result}`) })();
  7. $PSPVUJOFT suspend fun doSomething(value: Int): Int { delay(1000) return value

    * value } fun main() = runBlocking { println("Start task") val result = doSomething(100) println("Result: $result") }
  8. $PSPVUJOFT suspend fun doSomething(value: Int): Int { delay(1000) return value

    * value } fun main() = runBlocking { println("Start task") val result = doSomething(100) println("Result: $result") }
  9. $PSPVUJOFT suspend fun doSomething(value: Int): Int { delay(1000) return value

    * value } fun main() = runBlocking { println("Start task") val result = doSomething(100) println("Result: $result") }
  10. $PSPVUJOF4DPQFΛ࣮૷͢Δ suspend fun doSomething(value: Int): Int { delay(1000) return value

    * value } fun main() = runBlocking { println("Start task") val result = doSomething(100) println("Result: $result") } ݱࡏͷ࣮ߦεϨουΛݩʹ CoroutineScopeΛ࡞ͬͯ ࣮ߦ׬ྃ·Ͱ଴ͬͯΔ
  11. $PSPVUJOF4DPQFΛ࣮૷͢Δ class SimpleCoroutineScope(ui: CoroutineDispatcher) : CoroutineScope { // ਌JobΛ࡞Δ(࡞Ε) private

    val job: Job = Job() // σϑΥϧτͷڍಈͱͯ͠
 // ਌Job͸jobϓϩύςΟͷ΍ͭ
 // ࣮ߦίϯςΩετ͸ίϯετϥΫλҾ਺uiΛ༻͍Δ override val coroutineContext: CoroutineContext = job + ui }
  12. $PSPVUJOF4DPQFΛ࣮૷͢Δ class SimpleCoroutineScope : CoroutineScope { // ਌JobΛ࡞Δ(࡞Ε) private val

    job: Job = Job() // σϑΥϧτͷڍಈͱͯ͠
 // ਌Job͸jobϓϩύςΟͷ΍ͭ
 // ࣮ߦίϯςΩετ͸mainϧʔϓΛ༻͍Δ override val coroutineContext: CoroutineContext = job + Dispatchers.Main }
  13. $PSPVUJOF4DPQFΛ࣮૷͢Δ class SimpleCoroutineScope : CoroutineScope { // ਌JobΛ࡞Δ(࡞Ε) private val

    job: Job = Job() // σϑΥϧτͷڍಈͱͯ͠
 // ਌Job͸jobϓϩύςΟͷ΍ͭ
 // ࣮ߦίϯςΩετ͸IO Pool(※Threadͱ͸ݶΒͳ͍)Λ༻͍Δ override val coroutineContext: CoroutineContext = job + Dispatchers.IO }
  14. $PSPVUJOF4DPQFMBVODI͢Δ class SimpleCoroutineScope : CoroutineScope { // ਌JobΛ࡞Δ(࡞Ε) private val

    job: Job = Job() // σϑΥϧτͷڍಈͱͯ͠
 // ਌Job͸jobϓϩύςΟͷ΍ͭ
 // ࣮ߦίϯςΩετ͸mainϧʔϓΛ༻͍Δ override val coroutineContext: CoroutineContext = job + Dispatchers.Main }
  15. $PSPVUJOF4DPQFMBVODI͢Δ class SimpleCoroutineScope : CoroutineScope { private val job: Job

    = Job() override val coroutineContext: CoroutineContext = job + Dispatchers.Main fun foo() { launch { // ਌Λjob // ࣮ߦίϯςΩετΛmainϧʔϓͱͯ͠ // CoroutineΛىಈ͠ॲཧΛ࣮ߦ͢Δ val result = doSomething() } } }
  16. $PSPVUJOF4DPQFMBVODI͢Δ class SimpleCoroutineScope : CoroutineScope { // ਌JobΛ࡞Δ(࡞Ε) private val

    job: Job = Job() // σϑΥϧτͷڍಈͱͯ͠
 // ਌Job͸jobϓϩύςΟͷ΍ͭ
 // ࣮ߦίϯςΩετ͸IO Pool(※Threadͱ͸ݶΒͳ͍)Λ༻͍Δ override val coroutineContext: CoroutineContext = job + Dispatchers.IO }
  17. $PSPVUJOF4DPQFMBVODI͢Δ class SimpleCoroutineScope : CoroutineScope { private val job: Job

    = Job() override val coroutineContext: CoroutineContext = job + Dispatchers.IO fun foo() { launch { // ਌Λjob // ࣮ߦίϯςΩετΛIO Poolͱͯ͠ // CoroutineΛىಈ͠ॲཧΛ࣮ߦ͢Δ val result = doSomething() } } }
  18. TVTQFOEGVODUJPOΛ࣮૷͢Δ suspend fun doSomething(value: Int): Int { delay(1000) return value

    * value } fun main() = runBlocking { println("Start task") val result = doSomething(100) println("Result: $result") }
  19. TVTQFOEGVODUJPOΛ࣮૷͢Δ suspend fun doSomething(value: Int): Int { delay(1000) return value

    * value } fun main() = runBlocking { println("Start task") val result = doSomething(100) println("Result: $result") } ͜Εsuspend function
  20. TVTQFOEGVODUJPOΛ࣮૷͢Δ function sleep(milliSeconds) { return new Promise(resolve => setTimeout(resolve, milliSeconds));

    } async function doSomething(value) { await sleep(1000); return value * value; } (async() => { console.log("Start task."); const result = await doSomething(100); console.log(`Result: ${result}`) })();
  21. TVTQFOEGVODUJPOΛ࣮૷͢Δ function sleep(milliSeconds) { return new Promise(resolve => setTimeout(resolve, milliSeconds));

    } async function doSomething(value) { await sleep(1000); return value * value; } (async() => { console.log("Start task."); const result = await doSomething(100); console.log(`Result: ${result}`) })(); Ԟ஍Ͱ͜Ε૬౰ͷͳʹ͔Λ
 ࣮૷͢Δඞཁ͕͋Δ
  22. TVTQFOEGVODUJPOΛ࣮૷͢Δ suspend fun doSomething(value: Int): Int = suspendCoroutine { continuation

    -> continuation.resume(value * value) } suspend fun doSomething(value: Int): Int = suspendCoroutine { continuation -> continuation.resumeWithException(Throwable()) }
  23. طଘίʔυΛTVTQFOEGVO w$14 ͍ΘΏΔDBMMCBDLܗࣜ ͔ΒҠߦ͍ͨ͠৔߹ fun doSomethingAsync(value: Int, listener: Listener) {

    if (value <= 0) { listener.onError(Throwable()) } else { listener.onSuccess(value) } } suspend fun doSomething(value: Int): Int = suspendCoroutine { doSomethingAsync(value, object : Listener { override fun onSuccess(value: Int) { it.resume(value) } override fun onError(e: Throwable) { it.resumeWithException(e) } }) }
  24. طଘίʔυΛTVTQFOEGVO w3FBDUJWFd͔ΒҠߦ͍ͨ͠৔߹͸ม׵༻ϥΠϒϥϦΛ࢖͏
 ҎԼ͸3Y+BWBͷྫ 
 fun doSomethingSingle(value: Int): Single<Int> = Single.just(value

    * value) suspend fun doSomething(value: Int): Int = doSomethingSingle(value).await() implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:1.0.1"
  25. ྫ֎र͍͍ͨ launch { try { val result = doSomething() }

    catch (e: Throwable) { // } } launch { runCatching { doSomething() } // Result<T>͕ฦ٫͞ΕΔ .onSuccess { value -> } .onFailure { throwable -> } } ,PUMJO͔Β௥ՃͷSVO$BUDIJOHਪ঑
  26. ࣮ߦίϯςΩετม͍͑ͨ class SimpleCoroutineScope : CoroutineScope { private val job: Job

    = Job() override val coroutineContext: CoroutineContext = job + Dispatchers.Main fun execute() { launch { // Main runCatching { // Main withContext(Dispatchers.IO) { // IO doSomething() } } .onSuccess { value -> // Main } .onFailure { throwable -> // Main } } } }
  27. Ωϟϯηϧ͍ͨ͠ $ static async ValueTask<int> DoSomething(int value, CancellationToken token) {

    await Task.Delay(1000); token.ThrowIfCancellationRequested(); return value * value; } static async Task MainAsync(string[] args) { Console.WriteLine("Start task"); var cancellable = new CancellationTokenSource(); var task = DoSomething(100, cancellable.Token); cancellable.Cancel(); var result = await task; Console.WriteLine($"result: {result}"); }
  28. Ωϟϯηϧ͍ͨ͠ &4 async function doSomething(value, token) { await sleep(1000); await

    token.rejectIfCancelled(); return value * value; } (async() => { const cancellable = new Cancellable(); const finalize = () => cancellable.cancel(); process.on('exit', finalize); console.log("Start task."); doSomething(100, cancellable.token); console.log(`Result: ${result}`); process.removeListener('exit', finalize); })(); Cancellable.js https://gist.github.com/uzzu/7d6e89fafc4bcde1c6f6d82a3d164409 ˢ͸ྫ͕ѱ͍͕OPEFͰϓϩηεؒ௨৴ͭͭ͠௕ظλεΫ࣮ߦͯͯ͠ʜͳ࣌ͱ͔
  29. Ωϟϯηϧ͍ͨ͠ class SimpleCoroutineScope : CoroutineScope { private val job: Job

    = Job() override val coroutineContext: CoroutineContext = job + Dispatchers.Main fun onDestroy() { job.cancel() } }
  30. Ωϟϯηϧ͍ͨ͠ class SimpleCoroutineScope : CoroutineScope { private val job: Job

    = Job() override val coroutineContext: CoroutineContext = job + Dispatchers.Main fun onDestroy() { job.cancel() } } ࢠͷJob(Coroutine)͕શ෦cancel͞ΕΔ ݸผʹcancel͍ͨ͠έʔεʹ͍ͭͯ͸লུ
  31. ଞτϐοΫฉ͖͍ͨࣄ͋Ε͹ޙ΄ͲͲ͏ͧ w "EWBODFE
 3Y+BWBΛར༻࣮ͨ͠૷ͱͷൺֱΛͯ͠ΈΑ͏
 TVTQFOEGVODUJPOΛෳ਺૸Β͍ͤͨBTZODͷར༻ํ๏ͱ஫ҙ఺
 +BWBίʔυͱͷ૬ޓӡ༻
 .VUFY
 ଟॏݺͼग़͠๷ࢭIPUMBVODI IPUTVTQFOEGVODUJPO ໋໊͸ద౰

    
 6OJU5FTUͷॻ͖ํ
 $PSPVUJOF4UBSU $PSPVUJOF&YDFQUJPO)BOEMFS TVTQFOE$PSPVUJOF$POUJOVBUJPOγϦʔζ 
 ଞඈ͹ౕͨ͠
 $IBOOFM "DUPS 1SPEVDFS w %FFQ%JWJOH
 KPC EJTQBUDIFS  ʜ ͬͯԿ
 ͲΜͳίʔυʹͳΔͷόΠτίʔυݟͳ͕Β
 $PSPVUJOFͷத਎Ͳ͏ͳͬͯΜͷιʔείʔυಡΈͳ͕Β
 NVMUJQMBUGPSNؔ࿈