मैं jvm के लिए एक kotlin coroutine आधारित नेटवर्किंग ढांचा स्थापित कर रहा हूँ। क्लाइंट और सर्वर वर्ग CoroutineScope को लागू करते हैं, और coroutinecontext के लिए ओवरराइड Dispatchers.IO है, क्योंकि मुझे पूरा यकीन है कि ऐसे मामले के लिए उपयोग करने के लिए सही डिस्पैचर है। हालांकि, मैं मुख्य धागे पर पढ़े गए पैकेट को संभालना चाहता हूं, या कम से कम वह विकल्प प्रदान करना चाहता हूं। दस्तावेज़ीकरण को पढ़े बिना, मैंने डिस्पैचर्स.मेन का उपयोग किया, जो अब मुझे एहसास हुआ कि एंड्रॉइड यूआई थ्रेड के लिए है। क्या कोई प्रेषक है जिसका उपयोग मैं मुख्य धागे पर कोरआउटिन चलाने के लिए कर सकता हूं? यदि नहीं, तो मैं एक बनाने के बारे में कैसे जाउंगा?

मैंने एक थ्रेड के आधार पर डिस्पैचर बनाने के तरीके के बारे में कोटलिन दस्तावेज़ीकरण को देखा है, लेकिन मुझे newSingleThreadContext के अलावा कुछ भी नहीं मिला जो एक नया थ्रेड बनाता है। मुझे यह भी पता चला कि जावा एक्ज़ीक्यूटर से डिस्पैचर बनाना संभव है, लेकिन मुझे अभी भी यकीन नहीं है कि इसे पहले से मौजूद थ्रेड तक कैसे सीमित किया जाए।

class AbstractNetworkComponent : CoroutineScope {
    private val packetProcessor = PacketProcessor()
    private val job = Job()
    override val coroutineContext = job + Dispatchers.IO
}

class PacketProcessor : CoroutineScope {

    private val job = Job()
    override val coroutineContext = job + Dispatchers.Main //Android only!
    private val packetHandlers = mutableMapOf<Opcode, PacketHandlerFunc>()

    fun handlePacket(opcode: Opcode, packet: ReceivablePacket, networker: Writable) {
        launch(coroutineContext) {
            packetHandlers[opcode]?.invoke(packet, networker)
        }
    }
}

तो डिस्पैचर्स के साथ। एंड्रॉइड घटक गायब होने के कारण मुझे एक अवैधस्टेट अपवाद मिलता है। क्या डिस्पैचर बनाने का कोई तरीका है जो मुख्य धागे को उसके पूरा होने तक रोकता है (जैसे रनब्लॉकिंग करता है?) धन्यवाद!

5
Yonatan Ginsburg 15 जिंदा 2019, 04:28

2 जवाब

सबसे बढ़िया उत्तर

runBlocking ठीक वही है जो आपको चाहिए। यह एक डिस्पैचर बनाता है और इसे कोरआउटिन संदर्भ में सेट करता है। आप प्रेषक तक पहुंच सकते हैं

coroutineContext[ContinuationInterceptor] as CoroutineDispatcher

और फिर आप इसे किसी ऐसे ऑब्जेक्ट को पास कर सकते हैं जो CoroutineScope लागू करता है या जो कुछ भी आप इसके साथ करना चाहते हैं। यहाँ कुछ नमूना कोड है:

import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers.IO
import kotlin.coroutines.ContinuationInterceptor

fun main() {
    println("Top-level: current thread is ${Thread.currentThread().name}")
    runBlocking {
        val dispatcher = coroutineContext[ContinuationInterceptor]
                as CoroutineDispatcher
        ScopedObject(dispatcher).launchMe().join()
    }
}

class ScopedObject(dispatcher: CoroutineDispatcher) : CoroutineScope {
    override val coroutineContext = Job() + dispatcher

    fun launchMe() = launch {
        val result = withContext(IO) {
            "amazing"
        }
        println("Launched coroutine: " +
                "current thread is ${Thread.currentThread().name}, " +
                "result is $result")
    }
}

यह प्रिंट करेगा

Top-level: current thread is main
Launched coroutine: current thread is main, result is amazing
3
Marko Topolnik 15 जिंदा 2019, 13:23

Coroutines के साथ UI प्रोग्रामिंग के लिए मार्गदर्शिका kotlinx.coroutines में तीन मॉड्यूल हैं जो विभिन्न UI एप्लिकेशन लाइब्रेरी के लिए coroutine संदर्भ प्रदान करते हैं:

  • kotlinx-coroutines-android -- डिस्पैचर्स .Android के लिए मुख्य संदर्भ अनुप्रयोग।
  • kotlinx-coroutines-javafx -- डिस्पैचर्स जावाएफएक्स यूआई के लिए जावाएफएक्स संदर्भ अनुप्रयोग।
  • kotlinx-coroutines-swing -- डिस्पैचर्स .स्विंग UI के लिए स्विंग प्रसंग अनुप्रयोग।

साथ ही, UI डिस्पैचर Dispatchers.Main के माध्यम से kotlinx-coroutines-core और संबंधित कार्यान्वयन (Android, JavaFx या Swing) को ServiceLoader API द्वारा खोजा गया है। उदाहरण के लिए, यदि आप JavaFx एप्लिकेशन लिख रहे हैं, तो आप Dispatchers.Main या Dispachers.JavaFx एक्सटेंशन का उपयोग कर सकते हैं, यह वही ऑब्जेक्ट होगा।

1
Sergey 15 जिंदा 2019, 10:59