为iOS编写Kotlin Native协程后台Dispatcher遇非法引用异常求助
kotlin.native.IncorrectDereferenceException for GCD Global Queue Coroutine Dispatcher in Kotlin/Native iOS The exception you're hitting comes directly from Kotlin/Native's memory safety model, which blocks non-shared (non-frozen) objects from being accessed across different threads. Your current dispatcher passes a Runnable created on one thread to a GCD global queue thread, but that Runnable (and any objects it captures) aren't marked safe for cross-thread use.
Here's how to fix this:
Step 1: Freeze the Runnable for Cross-Thread Access
Update your NsQueueDispatcher to freeze the Runnable before passing it to dispatch_async. Freezing makes the object (and all its referenced objects) immutable, which lets the runtime know it's safe to access across threads:
val runCoroutineDispatcher: CoroutineContext = NsQueueDispatcher object NsQueueDispatcher : CoroutineDispatcher() { override fun dispatch(context: CoroutineContext, block: Runnable) { // Freeze the block to enable safe cross-thread execution val frozenBlock = block.freeze() dispatch_async( dispatch_get_global_queue( NSNumber(double = DISPATCH_QUEUE_PRIORITY_DEFAULT.toDouble()).integerValue, 0 ) ) { frozenBlock.run() } } }
Why This Resolves the Exception
Kotlin/Native uses thread confinement by default: objects can only be used on the thread they were created on unless they're frozen. By freezing the Runnable, you're explicitly marking it as immutable and safe for use on any thread, which eliminates the IncorrectDereferenceException.
Additional Tips
- If your coroutine block captures mutable state, use thread-safe constructs like
AtomicReferencefromkotlin.native.concurrentinstead of regular variables. - For most background work, you can also use the built-in
Dispatchers.Defaultfromkotlinx.coroutines—it's already optimized for Kotlin/Native background tasks. But if you need a custom GCD-based dispatcher, the fix above will work perfectly.
Testing your sample code with the modified dispatcher should now run without errors:
CoroutineScope(runCoroutineDispatcher).launch { println("Hello World") }
内容的提问来源于stack exchange,提问作者Sebastian Ohm

