使用给出的coroutine context调用指定的挂起代码块block,挂起直到它完成并返回结果
对block产生的结果context来自`coroutineContext + context` (see [CoroutineContext.plus]) *** 作合并当前的coroutineContext和指定的context。这个挂起函数是可取消的。它立即检查结果context的取消,如果它不是active[CoroutineContext.isActive].就抛出[CancellationException]异常。
这个函数使用来自新的context的派发器,如果一个新的派发器被指定,就把block的执行转移到不同的线程,并且完成时,返回原来的派发器。withContext的调用结果是以可取消的方式派发到原来的context,这意味着withContext调用所在的原来的coroutineContext在它的派发器开始执行这段代码的时候被取消,它会放弃withContext的结果并抛出异常
public suspend funwithContext( context: CoroutineContext, block: suspend CoroutineScope.() -> T ): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return suspendCoroutineUninterceptedOrReturn sc@ { uCont -> // compute new context val oldContext = uCont.context val newContext = oldContext + context // always check for cancellation of new context newContext.checkCompletion() // FAST PATH #1 -- new context is the same as the old one if (newContext === oldContext) { val coroutine = ScopeCoroutine(newContext, uCont) return@sc coroutine.startUndispatchedOrReturn(coroutine, block) } // FAST PATH #2 -- the new dispatcher is the same as the old one (something else changed) // `equals` is used by design (see equals implementation is wrapper context like ExecutorCoroutineDispatcher) if (newContext[ContinuationInterceptor] == oldContext[ContinuationInterceptor]) { val coroutine = UndispatchedCoroutine(newContext, uCont) // There are changes in the context, so this thread needs to be updated withCoroutineContext(newContext, null) { return@sc coroutine.startUndispatchedOrReturn(coroutine, block) } } // SLOW PATH -- use new dispatcher val coroutine = DispatchedCoroutine(newContext, uCont) coroutine.initParentJob() block.startCoroutineCancellable(coroutine, coroutine) coroutine.getResult() } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)