2017-06-12 16 views
2

私は、次のスニペットを抱えているがkotlinコルーチンとメインハンドラの関係

verticalLayout { 
     gravity = Gravity.CENTER 
     button("BUTTON").onClick { 
      trace("click on process") 
      runBlocking { 
       trace("blocking start") // #1 
       delay(20000L) #2 
       trace("blocking end") // #3 
      } 
      trace("click process end") 
     } 
    } 

トレースが現在のスレッド名とLog.eを使用してメッセージをログアウトするユーティリティ関数として定義された関数である

I期待とログは、すべてのトレース機能は、メインスレッドで呼び出されるショーとしてボタン、すべてのコードの実行をクリックし 20000Lミリ秒と無ANRダイアログ内#1の後に表示されます#3のためにログが

を示すが、奇妙なことは、20000Lミリ秒の間に、起こりました、私は、ボタンを離したときのonClickメソッドが終了したときにボタンが

iは コルーチンがにCPSを使用してコンパイラの魔法があるという生の概念を持っていた、右クリックした後、その後、私が押された状態が復元されて実現しても 押された状態を開催しますそう

delay(20000L,callback = { trace("blocking end ")}) 

に従うように、コールバック形式の関数にコードを変換するI持って、実際にコールバック(たとえば、トレース(「ブロッキング終了を呼び出し、最後に次の質問

  1. "))答えがメインルーパーか何か(nodejsの場合、eventloopの場合)、コルーチンのフレームワークを適応させ、コルーチンがイベントをキューに入れさせるべきでしょうか?
  2. coroutineは実際にはコンパイラの魔法ですが、上記のスニペットと同じコードを書くことができますが、ANRをトリガしませんが、20000Lの状態を維持しますか?
+2

実際に作る必要がないという前提がたくさんあるようです。 'runBlocking'の呼び出しは、呼び出されたのと同じスレッド上で実行されるコルーチンを作成し、中断ポイントのスレッドをブロックします。 'delay'への呼び出しは、' onClick'関数が実行されているスレッドをブロックします。 – marstran

+0

達成しようとしていることは明確ではありません。現在の動作は@marstranによって説明されています。 UIスレッドから 'runBlocking'と組み合わせて' delay'を呼び出すべきではありません。 'launch(CommonPool)'を呼び出すか、 'delay'を呼び出さないで他のスレッドに移動してください。 – xap4o

答えて

3

runBlockingは、コルーチンの実行中に呼び出されるスレッドをブロックするため、この方法で名前が付けられています。具体的には、runBlockingでUIスレッドをブロックしています。

runBlockinglaunch(UI)に置き換えて、UIスレッドをブロックせずにUIスレッドでバックグラウンドコルーチンを開始することができます。コロンで作業するさまざまな方法の詳細については、とGuide to UI programming with coroutinesで学ぶことができます。

関連する問題