কোটলিন কার্টিনে কার্য স্থগিতকরণের অর্থ কী


118

আমি কোটলিন Coroutine পড়ছি এবং জানি যে এটি suspendফাংশনের উপর ভিত্তি করে । কিন্তু suspendমানে কি?

কর্টিন বা ফাংশন স্থগিত?

Https://kotlinlang.org/docs/references/coroutines.html থেকে

মূলত, করোটাইনগুলি এমন একটি গণনা যা কোনও থ্রেড ব্লক না করে স্থগিত করা যায়

শুনেছি লোকেরা প্রায়শই "সাসপেন্ড ফাংশন" বলে say তবে আমি মনে করি এটি কার্টিনই স্থগিত হয়ে যায় কারণ এটি ফাংশনটি শেষ হওয়ার অপেক্ষায় রয়েছে? "সাসপেন্ড" এর অর্থ সাধারণত "অপারেশন বন্ধ করুন", এক্ষেত্রে কর্টিন অলস।

We আমাদের কি কর্টিন স্থগিত করা উচিত?

কোন কর্টিন স্থগিত হয়?

Https://kotlinlang.org/docs/references/coroutines.html থেকে

উপমা অব্যাহত রাখতে, অপেক্ষা () একটি স্থগিত ফাংশন হতে পারে (অতএব এটি একটি অ্যাসিঙ্ক}} ব্লকের মধ্যে থেকে কলযোগ্য) যা কিছু গণনা না করা এবং তার ফলাফল না ফেরানো পর্যন্ত একটি কর্টিন স্থগিত করে:

async { // Here I call it the outer async coroutine
    ...
    // Here I call computation the inner coroutine
    val result = computation.await()
    ...
}

🤔 এটি বলে যে "কিছু গণনা শেষ না হওয়া পর্যন্ত কোনও কর্টিন স্থগিত করে", তবে করাউটিন হালকা ওজনের থ্রেডের মতো। সুতরাং যদি কর্টিন স্থগিত করা হয় তবে গণনা কীভাবে করা যায়?

আমরা দেখি awaitযে আহ্বান জানানো হয়েছে computation, সুতরাং এটি asyncফিরে আসতে পারে Deferredযার অর্থ এটি অন্য কর্টিন শুরু করতে পারে

fun computation(): Deferred<Boolean> {
    return async {
        true
    }
}

🤔 উদ্ধৃতিটি বলে যে কোনও কর্টিন স্থগিত করে । এর অর্থ কি suspendবাইরের asyncকর্টিন, suspendনা অভ্যন্তরের computationকর্টিন?

এর suspendঅর্থ এই যে বাইরের asyncকর্টিনটি awaitঅভ্যন্তরীণ computationকর্টিন সমাপ্ত হওয়ার জন্য অপেক্ষা করছে ( এটি বাহ্যিক asyncকর্টিন) অলৌকিক (তাই নামটি স্থগিত করা) এবং থ্রেড পুলে থ্রেডটি ফেরত দেয় এবং যখন সন্তানের computationকর্টিন শেষ হয়, তখন এটি (বাহ্যিক বাহ্যিক বাহিনী)async কর্টিন) ) জেগে, পুল থেকে অন্য থ্রেড নেয় এবং অবিরত থাকে?

আমি থ্রেডটি উল্লেখ করার কারণটি হ'ল https://kotlinlang.org/docs/tutorials/coroutines-basic-jvm.html

কর্টিন অপেক্ষা করার সময় থ্রেডটি পুলটিতে ফিরে আসে এবং যখন অপেক্ষাটি শেষ হয়, তখন পুলটি একটি মুক্ত থ্রেডে পুনরায় শুরু হয়

উত্তর:


113

সাসপেন্ডিং ফাংশনগুলি প্রতিটি কর্টিনগুলির কেন্দ্রে থাকে। একটি স্থগিতকরণ ফাংশনটি কেবল একটি ফাংশন যা পরে থামানো এবং পুনরায় শুরু করা যেতে পারে। তারা একটি দীর্ঘ চলমান অপারেশন চালিয়ে দিতে পারে এবং এটি অবরুদ্ধ না করে এটি শেষ হওয়ার জন্য অপেক্ষা করতে পারে।

স্থগিতকরণের ক্রিয়াকলাপটির মূল বাক্যাংশ suspendকীওয়ার্ডটি সংযোজন ব্যতীত নিয়মিত ফাংশনের সাথে সমান । এটি একটি প্যারামিটার নিতে পারে এবং একটি রিটার্ন টাইপ থাকতে পারে। তবে, সাসপেন্ডিং ফাংশনগুলি কেবলমাত্র অন্য স্থগিতকারী ফাংশন বা কোনও কর্টিনের মধ্যেই ডাকা যেতে পারে।

suspend fun backgroundTask(param: Int): Int {
     // long running operation
}

হুডের অধীনে, সাসপেন্ড ফাংশনগুলি কম্পাইলার দ্বারা স্থগিত কীওয়ার্ড ব্যতীত অন্য ফাংশনে রূপান্তরিত করা হয়, এটি টাইপের একটি অতিরিক্ত পরামিতি নেয় Continuation<T>। উদাহরণস্বরূপ উপরের ফাংশনটি এই সংকলক দ্বারা রূপান্তরিত হবে:

fun backgroundTask(param: Int, callback: Continuation<Int>): Int {
   // long running operation
}

Continuation<T> এমন একটি ইন্টারফেস যা দুটি ফাংশন ধারণ করে যা প্রত্যাবর্তন মূল্যের সাথে কর্টিন পুনরায় শুরু করতে অনুরোধ করা হয় বা ফাংশন স্থগিতের সময় কোনও ত্রুটি ঘটলে ব্যতিক্রম সহ with

interface Continuation<in T> {
   val context: CoroutineContext
   fun resume(value: T)
   fun resumeWithException(exception: Throwable)
}

4
আর একটি রহস্য উন্মোচন! গ্রেট!
উইন্ডারাইডার

16
আমি ভাবছি এই ফাংশনটি আসলে কীভাবে বিরতি দেওয়া হয়েছে? তারা সবসময় বলে যে suspend funথামানো যেতে পারে তবে ঠিক কীভাবে?
উইন্ডারাইডার

2
@ উইন্ড্রাইডার এর ঠিক অর্থ হ'ল বর্তমান থ্রেডটি অন্য কোনও কর্টিন চালানো শুরু করে এবং এটি পরে ফিরে আসবে।
জোফ্রে

2
আমি "রহস্যময়" প্রক্রিয়াটি আবিষ্কার করেছি। এটি সরঞ্জাম> কোটলিন> বাইটকোড> ডিকম্পাইল বিটিএন এর সহায়তায় সহজেই উন্মোচন করা যায়। এটি দেখায় যে কীভাবে তথাকথিত "সাসপেনশন পয়েন্ট" প্রয়োগ করা হয় - ধারাবাহিকতা ইত্যাদির মাধ্যমে। যে কেউ নিজের জন্য নজর রাখতে পারে।
উইন্ডারাইডার

4
@ বুজা এখানে রোমান এলিজারভের 2017 সালের একটি আলোচনা রয়েছে যা এটি বাইটোকোড স্তরে ব্যাখ্যা করেছে।
মার্কো টপলনিক

30

কোনও কর্টিন স্থগিত করার অর্থ হ'ল বোঝার জন্য, আমি আপনাকে এই কোডটি অনুসরণ করার পরামর্শ দিচ্ছি:

import kotlinx.coroutines.Dispatchers.Unconfined
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

var continuation: Continuation<Int>? = null

fun main() = runBlocking {
    launch(Unconfined) {
        val a = a()
        println("Result is $a")
    }
    10.downTo(0).forEach {
        continuation!!.resume(it)
    }
}

suspend fun a(): Int {
    return b()
}

suspend fun b(): Int {
    while (true) {
        val i = suspendCoroutine<Int> { cont -> continuation = cont }
        if (i == 0) {
            return 0
        }
    }
}

UnconfinedCoroutine ডেস্প্যাচার জাদু ঘটিয়েছে coroutine ডিসপ্যাচিং এবং সরাসরি আমাদের খালি coroutines উপর ফোকাস করতে পারবেন।

launchব্লকের অভ্যন্তর কোডটি launchকলটির অংশ হিসাবে বর্তমান থ্রেডের সাথে সাথেই সম্পাদন করা শুরু করে । যা ঘটে তা হ'ল:

  1. মূল্যনির্ধারণ val a = a()
  2. এই চেইন b(), পৌঁছনো suspendCoroutine
  3. ফাংশনটি b()পাস করা ব্লকটি কার্যকর করে suspendCoroutineএবং তারপরে একটি বিশেষ COROUTINE_SUSPENDEDমান প্রদান করে। এই মানটি কোটলিন প্রোগ্রামিং মডেলের মাধ্যমে পর্যবেক্ষণযোগ্য নয়, তবে এটি সংকলিত জাভা পদ্ধতিটি করে।
  4. ফাংশন a(), এই রিটার্ন মানটি দেখে তা নিজেও এটি ফেরত দেয়।
  5. launchব্লক একই আছে এবং নিয়ন্ত্রণ এখন পর লাইন ফেরৎ launchআবাহন:10.downTo(0)...

মনে রাখবেন যে, এই মুহুর্তে, আপনার একই প্রভাব রয়েছে যেন launchব্লকের ভিতরে থাকা fun mainকোড এবং আপনার কোড একই সাথে সম্পাদন করে। এটি কেবল ঘটে যা এই একক নেটিভ থ্রেডে ঘটছে তাই launchব্লকটি "স্থগিত" করা হয়েছে।

এখন, ভিতরে forEachলুপিং কোড, প্রোগ্রাম সার্চ continuationযে b()ফাংশন লিখেছে এবং resumesএর মান সঙ্গে এটি 10resume()এমনভাবে বাস্তবায়ন করা হয়েছে যাতে এটি suspendCoroutineকল হয়ে যায় যে আপনি যে মানটি দিয়ে গেছেন তার সাথে কলটি ফিরে এসেছে So সুতরাং আপনি হঠাৎ নিজেকে নির্বাহের মাঝখানে খুঁজে পাবেন b()। আপনি যে মানটি পাস করেছেন তা resume()নির্ধারিত হয় iএবং তার বিপরীতে পরীক্ষা করা হয় 0। যদি এটি শূন্য না হয়, while (true)লুপটি ভেতরে চলে যায় b(), আবার পৌঁছে যায় suspendCoroutine, আপনার resume()কলটি আবার কোন দিকে ফিরে আসে এবং এখন আপনি অন্য লুপিংয়ের ধাপটি পেরিয়ে যান forEach()। অবশেষে আপনি আবার শুরু না হওয়া পর্যন্ত এটি চলে 0, তারপরে printlnবিবৃতিটি চলে এবং প্রোগ্রামটি সম্পূর্ণ হয়।

উপরের বিশ্লেষণটি আপনাকে গুরুত্বপূর্ণ স্বীকৃতি দেবে যে "একটি কর্টিন স্থগিত করা" এর অর্থ নিয়ন্ত্রণটি অভ্যন্তরীণ launchআবেদনের দিকে ফিরিয়ে দেওয়া (বা আরও সাধারণভাবে কর্টিন বিল্ডার )। যদি কোনও কর্টিন পুনরায় শুরু হওয়ার পরে আবার স্থগিত করে, resume()কলটি শেষ হয় এবং কলকারীর কাছে ফিরে আসে নিয়ন্ত্রণ resume()

কোনও কর্টিন প্রেরণকারীর উপস্থিতি এই যুক্তিটিকে কম পরিষ্কার করে দেয় কারণ তাদের বেশিরভাগই তাত্ক্ষণিকভাবে আপনার কোডটিকে অন্য থ্রেডে জমা দেয়। সেক্ষেত্রে উপরের গল্পটি অন্যান্য থ্রেডে ঘটে এবং কর্টিন প্রেরণকারীও সেই continuationবস্তুটি পরিচালনা করে যাতে ফেরতের মান উপলব্ধ হলে এটি পুনরায় শুরু করতে পারে।


19

প্রথমত, এই আইএমওটি বোঝার সর্বোত্তম উত্স হ'ল রোমান এলিজারভের "ডিপ ডাইভ ইন করাউটিনস" টক ।

কর্টিন বা ফাংশন স্থগিত?

একটি স্থগিত কলিং ing ফাংশন স্থগিত গুলি coroutine, বর্তমান থ্রেড অর্থ অন্য coroutine নির্বাহ শুরু করতে পারেন। সুতরাং, কর্টিনটি ফাংশনটির চেয়ে স্থগিত করা হবে বলে জানা গেছে।

প্রকৃতপক্ষে, সাসপেন্ডিং ফাংশনগুলির কল সাইটগুলিকে এই কারণে "সাসপেনশন পয়েন্ট" বলা হয়।

কোন কর্টিন স্থগিত হয়?

আসুন আপনার কোডটি দেখুন এবং কী ঘটে তা ভেঙে দিন:

// 1. this call starts a new coroutine (let's call it C1).
//    If there were code after it, it would be executed concurrently with
//    the body of this async
async {
    ...
    // 2. this is a regular function call
    val deferred = computation()
    // 4. because await() is suspendING, it suspends coroutine C1.
    //    This means that if we had a single thread in our dispatcher, 
    //    it would now be free to go execute C2
    // 7. once C2 completes, C1 is resumed with the result `true` of C2's async
    val result = deferred.await() 
    ...
    // 8. C1 can now keep going in the current thread until it gets 
    //    suspended again (or not)
}

fun computation(): Deferred<Boolean> {
    // 3. this async call starts a second coroutine (C2). Depending on the 
    //    dispatcher you're using, you may have one or more threads.
    // 3.a. If you have multiple threads, the block of this async could be
    //      executed in parallel of C1 in another thread. The control flow 
    //      of the current thread returns to the caller of computation().
    // 3.b. If you have only one thread, the block is sort of "queued" but 
    //      not executed right away, and the control flow returns to the 
    //      caller of computation(). (unless a special dispatcher or 
    //      coroutine start argument is used, but let's keep it simple).
    //    In both cases, we say that this block executes "concurrently"
    //    with C1.
    return async {
        // 5. this may now be executed
        true
        // 6. C2 is now completed, so the thread can go back to executing 
        //    another coroutine (e.g. C1 here)
    }
}

বাইরের asyncএকটি কর্টিন শুরু করে। এটি কল করার সময় computation(), অভ্যন্তরটি asyncদ্বিতীয় কর্টিন শুরু করে। তারপরে, অভ্যন্তরের কর্টিনের কার্যকারিতা শেষ না হওয়া পর্যন্ত বাইরের কর্টিনের await()কার্যকারিতা স্থগিত করার আহ্বান জানানো হয় । async async

আপনি একক থ্রেডের সাথে এটি দেখতেও পান: থ্রেডটি বাইরের শুরুটি কার্যকর করবে async, তারপরে কল computation()করে অভ্যন্তরে পৌঁছাবে async। এই মুহুর্তে, অভ্যন্তরীণ অ্যাসিঙ্কের দেহটি এড়িয়ে যায় এবং থ্রেডটি asyncএটি না পৌঁছানো পর্যন্ত বহিরাগতকে চালিত করে await()await()এটি একটি "সাসপেনশন পয়েন্ট", কারণ awaitএটি একটি সাসপেন্ডিং ফাংশন। এর অর্থ বাহ্যিক কর্টিন স্থগিত করা হয়েছে এবং এইভাবে থ্রেডটি অভ্যন্তরীণটিকে কার্যকর করতে শুরু করে। এটি হয়ে গেলে, এটি বাইরের শেষটি কার্যকর করতে ফিরে আসে async

স্থগিতকরণটির অর্থ কি এই যে বাইরের অ্যাসিনক কর্টিনটি অভ্যন্তরীণ গণনা কর্টিন সমাপ্তির জন্য অপেক্ষা (অপেক্ষা) করতে থাকে, এটি (বহিরাগত অ্যাসিঙ্ক কর্টিন) আইডলগুলি (অতএব নামটি স্থগিত করা হয়) এবং থ্রেড পুলে থ্রেডটি ফেরত দেয় এবং যখন শিশু গণনার কর্টিন সমাপ্ত হয় , এটি (বাইরের অ্যাসিঙ্ক কর্টিন) জেগে, পুল থেকে অন্য থ্রেড নেয় এবং চালিয়ে যায়?

হ্যাঁ, অবশ্যই

এটি আসলে যেভাবে অর্জন করা হয় তা হ'ল প্রতিটি স্থগিতকারী ফাংশনটিকে একটি রাষ্ট্র মেশিনে পরিণত করা, যেখানে প্রতিটি "রাষ্ট্র" এই স্থগিত ফাংশনের অভ্যন্তরে একটি স্থগিতাদেশের সাথে মিল রাখে। হুডের অধীনে, কোন সাসপেনশন পয়েন্টটি থেকে এটি কার্যকর করা উচিত সে সম্পর্কে তথ্য সহ ফাংশনটিকে একাধিকবার বলা যেতে পারে (এ সম্পর্কিত আরও তথ্যের জন্য আপনার লিঙ্কযুক্ত ভিডিওটি সত্যই দেখে নেওয়া উচিত)।


3
দুর্দান্ত উত্তর, আমি কর্টিনগুলির ক্ষেত্রে এটির মতো ধরণের সত্যিকারের মৌলিক ব্যাখ্যাটি মিস করি।
bernardo.g

কেন এটি অন্য কোনও ভাষায় প্রয়োগ করা হয় না? নাকি আমি কিছু মিস করছি? আমি এত দিন ধরে এই সমাধানটির বিষয়ে ভাবছি, কোটলিনের আনন্দের বিষয় আছে, তবে কেন টিএস বা
মরিচির

@PEZO ওয়েল কর্টাইনগুলি দীর্ঘকাল ধরে রয়েছে। কোটলিন এগুলি আবিষ্কার করেনি, তবে বাক্য গঠন এবং গ্রন্থাগার এগুলিকে আলোকিত করে। গোতে গোরোটাইন রয়েছে, জাভাস্ক্রিপ্ট এবং টাইপস্ক্রিপ্টের প্রতিশ্রুতি রয়েছে। কেবলমাত্র পার্থক্যটি তাদের ব্যবহারের সিনট্যাক্সের বিশদে রয়েছে। জেএসের asyncফাংশনগুলিকে এইভাবে চিহ্নিত করা এবং এখনও একটি প্রতিশ্রুতি ফিরিয়ে দেওয়া আমার পক্ষে বেশ বিরক্তিকর / বিরক্তিকর বলে মনে হচ্ছে।
জোফ্রে

দুঃখিত, আমার মন্তব্য পরিষ্কার ছিল না। আমি সাসপেন্ড কীওয়ার্ডটি উল্লেখ করছি। এটি অ্যাসিঙ্কের মতো নয়।
পেজো

রোমানের ভিডিওটি দেখানোর জন্য ধন্যবাদ। খাঁটি সোনা.
Denounce'IN

8

আমি খুঁজে পেয়েছি যে বোঝার সর্বোত্তম উপায় suspendহ'ল thisকীওয়ার্ড এবং coroutineContextসম্পত্তির মধ্যে সাদৃশ্য তৈরি করা ।

কোটলিন ফাংশনগুলি স্থানীয় বা বৈশ্বিক হিসাবে ঘোষণা করা যেতে পারে। স্থানীয় ফাংশনগুলিতে বৈজ্ঞানিকভাবে thisকীওয়ার্ড অ্যাক্সেস থাকে যখন বিশ্বব্যাপী হয় না।

কোটলিন ক্রিয়াকলাপগুলি suspendবা ব্লক হিসাবে ঘোষণা করা যেতে পারে । suspendক্রিয়াকলাপগুলি coroutineContextব্লক করে না এমন সময় ফাংশনগুলির যাদুতে সম্পত্তিতে অ্যাক্সেস থাকে ।

জিনিসটি হ'ল coroutineContextসম্পত্তিটি কোটলিন স্টাডলিবের "সাধারণ" সম্পত্তির মতো ঘোষিত হয় তবে এই ঘোষণাটি ডকুমেন্টেশন / নেভিগেশন উদ্দেশ্যে কেবল একটি স্টাব। বস্তুত coroutineContextহয় স্বকীয় সম্পত্তি builtin যে ফণা কম্পাইলার জাদু এই সম্পত্তি এটা পছন্দ ভাষা কীওয়ার্ড সচেতন সচেতন অধীনে উপায়।

কি thisশব্দ স্থানীয় কাজকর্মের জন্য আছে কি coroutineContextসম্পত্তির জন্য আছে suspendফাংশন: এটা সঞ্চালনের বর্তমান প্রসঙ্গে অ্যাক্সেস দেয়।

সুতরাং, আপনাকে সম্পত্তিতে suspendঅ্যাক্সেস পাওয়া দরকার coroutineContext- বর্তমানে সম্পাদিত কর্টিন প্রসঙ্গের উদাহরণ


5

ধারাবাহিকতার ধারণার একটি সহজ উদাহরণ আপনাকে দিতে চাইছি। এটি একটি সাসপেন্ড ফাংশনটি করে যা এটি স্থির করে / স্থগিত করতে পারে এবং তারপরে এটি চালিয়ে যায় / পুনরায় শুরু হয়। থ্রেড এবং সেম্যাফোোরের ক্ষেত্রে কর্টিনের চিন্তাভাবনা বন্ধ করুন। ধারাবাহিকতা এমনকি কলব্যাক হুকের ক্ষেত্রে এটি ভাবুন।

পরিষ্কার হওয়ার জন্য, কোনও suspendফাংশন ব্যবহার করে কোনও কর্টিনকে বিরতি দেওয়া যেতে পারে । এটি তদন্ত করতে দিন:

অ্যান্ড্রয়েডে আমরা উদাহরণস্বরূপ এটি করতে পারি:

var TAG = "myTAG:"
        fun myMethod() { // function A in image
            viewModelScope.launch(Dispatchers.Default) {
                for (i in 10..15) {
                    if (i == 10) { //on first iteration, we will completely FREEZE this coroutine (just for loop here gets 'suspended`)
                        println("$TAG im a tired coroutine - let someone else print the numbers async. i'll suspend until your done")
                        freezePleaseIAmDoingHeavyWork()
                    } else
                        println("$TAG $i")
                    }
            }

            //this area is not suspended, you can continue doing work
        }


        suspend fun freezePleaseIAmDoingHeavyWork() { // function B in image
            withContext(Dispatchers.Default) {
                async {
                    //pretend this is a big network call
                    for (i in 1..10) {
                        println("$TAG $i")
                        delay(1_000)//delay pauses coroutine, NOT the thread. use  Thread.sleep if you want to pause a thread. 
                    }
                    println("$TAG phwww finished printing those numbers async now im tired, thank you for freezing, you may resume")
                }
            }
        }

উপরে কোড নিম্নলিখিত মুদ্রণ:

I: myTAG: my coroutine is frozen but i can carry on to do other things

I: myTAG: im a tired coroutine - let someone else print the numbers async. i'll suspend until your done

I: myTAG: 1
I: myTAG: 2
I: myTAG: 3
I: myTAG: 4
I: myTAG: 5
I: myTAG: 6
I: myTAG: 7
I: myTAG: 8
I: myTAG: 9
I: myTAG: 10

I: myTAG: phwww finished printing those numbers async now im tired, thank you for freezing, you may resume

I: myTAG: 11
I: myTAG: 12
I: myTAG: 13
I: myTAG: 14
I: myTAG: 15

এটিকে এভাবে কাজ করার কথা ভাবুন:

এখানে চিত্র বর্ণনা লিখুন

সুতরাং আপনি যে চালু ফাংশনটি চালু করেছেন তা থামবে না, কেবলমাত্র একটি কর্টিন স্থগিত হবে যখন এটি অবিরত থাকবে। স্থগিত ফাংশনটি চালিয়ে থ্রেড থামানো হয়নি।

আমি মনে করি এই সাইটটি আপনাকে সোজা জিনিসগুলিতে সাহায্য করতে পারে এবং এটি আমার উল্লেখ।

আসুন কিছু শীতল করি এবং পুনরাবৃত্তির মাঝামাঝি সময়ে আমাদের সাসপেন্ড ফাংশনটি স্থির করি। আমরা পরে এটি পুনরায় শুরু করবonResume

নামক একটি ভেরিয়েবল সংরক্ষণ করুন continuationএবং আমরা আমাদের জন্য এটি কর্টাইনস ধারাবাহিকতা বস্তুর সাথে লোড করব:

var continuation: CancellableContinuation<String>? = null

suspend fun freezeHere() = suspendCancellableCoroutine<String> {
            continuation = it
        }

 fun unFreeze() {
            continuation?.resume("im resuming") {}
        }

এখন, আসুন আমাদের স্থগিত ফাংশনে ফিরে আসুন এবং এটি পুনরাবৃত্তির মাঝখানে স্থির করে তুলুন:

 suspend fun freezePleaseIAmDoingHeavyWork() {
        withContext(Dispatchers.Default) {
            async {
                //pretend this is a big network call
                for (i in 1..10) {
                    println("$TAG $i")
                    delay(1_000)
                    if(i == 3)
                        freezeHere() //dead pause, do not go any further
                }
            }
        }
    }

তারপরে অন্য কোথাও অনুরুপ পছন্দ করুন (উদাহরণস্বরূপ):

override fun onResume() {
        super.onResume()
        unFreeze()
    }

এবং লুপ চলতে থাকবে। এটি জানার জন্য আমাদের সুন্দর ঝরঝরে আমরা যে কোনও সময়ে একটি স্থগিতাদেশ ফাংশন হিমশীতল করতে পারি এবং কিছুক্ষণ মৌমাছি চলে যাওয়ার পরে এটি আবার চালু করতে পারি। আপনি চ্যানেলগুলিও দেখতে পারেন


4

অনেক ভাল উত্তর ইতিমধ্যে আছে, আমি অন্যদের জন্য একটি সহজ উদাহরণ পোস্ট করতে চাই।

রানব্লকিং ব্যবহারের কেস:

  • myMethod () suspendফাংশন করে
  • runBlocking { }অবরুদ্ধ উপায়ে একটি কর্টিন শুরু করে। এটি Threadক্লাসের সাথে আমরা কীভাবে সাধারণ থ্রেডগুলি ব্লক করেছিলাম এবং নির্দিষ্ট ইভেন্টের পরে অবরুদ্ধ থ্রেডগুলিতে বিজ্ঞপ্তি দিচ্ছিলাম তার সমান ।
  • runBlocking { }নেই ব্লক বর্তমান থ্রেড নির্বাহ coroutine পর্যন্ত (শরীরের মধ্যে {}) সম্পন্ন পরার

     override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
        Log.i(TAG,"Outer code started on Thread : " + Thread.currentThread().name);
        runBlocking {
            Log.d(TAG,"Inner code started  on Thread : " + Thread.currentThread().name + " making outer code suspend");
            myMethod();
        }
        Log.i(TAG,"Outer code resumed on Thread : " + Thread.currentThread().name);
    }
    
    private suspend fun myMethod() {
        withContext(Dispatchers.Default) {
        for(i in 1..5) {
            Log.d(TAG,"Inner code i : $i on Thread : " + Thread.currentThread().name);
        }
    }

এই ফলাফলগুলি:

I/TAG: Outer code started on Thread : main
D/TAG: Inner code started  on Thread : main making outer code suspend
// ---- main thread blocked here, it will wait until coroutine gets completed ----
D/TAG: Inner code i : 1 on Thread : DefaultDispatcher-worker-2
D/TAG: Inner code i : 2 on Thread : DefaultDispatcher-worker-2
D/TAG: Inner code i : 3 on Thread : DefaultDispatcher-worker-2
D/TAG: Inner code i : 4 on Thread : DefaultDispatcher-worker-2
D/TAG: Inner code i : 5 on Thread : DefaultDispatcher-worker-2
// ---- main thread resumes as coroutine is completed ----
I/TAG: Outer code resumed on Thread : main

প্রবর্তন ব্যবহারের কেস:

  • launch { } একযোগে একটি কর্টিন শুরু করে।
  • এর অর্থ হ'ল আমরা যখন লঞ্চটি নির্দিষ্ট করি তখন একটি কর্টিন workerথ্রেডে সঞ্চালন শুরু করে ।
  • workerথ্রেড এবং বাইরের থ্রেড (যেখান থেকে আমরা নামক launch { }) উভয় একই সময়ে চালানো হয়। অভ্যন্তরীণভাবে, জেভিএম প্রিম্পিটিভ থ্রেডিং সম্পাদন করতে পারে
  • সমান্তরালভাবে চালনার জন্য যখন আমাদের একাধিক কার্যের প্রয়োজন হয়, আমরা এটি ব্যবহার করতে পারি। আছে scopesযা কর্টিনের জীবনকাল নির্দিষ্ট করে। যদি আমরা নির্দিষ্ট করে থাকি GlobalScopeতবে প্রয়োগের আজীবন শেষ হওয়া অবধি কর্টিন কাজ করবে।

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
        Log.i(TAG,"Outer code started on Thread : " + Thread.currentThread().name);
    
        GlobalScope.launch(Dispatchers.Default) {
            Log.d(TAG,"Inner code started  on Thread : " + Thread.currentThread().name + " making outer code suspend");
            myMethod();
        }
        Log.i(TAG,"Outer code resumed on Thread : " + Thread.currentThread().name);
    }
    
    private suspend fun myMethod() {
        withContext(Dispatchers.Default) {
            for(i in 1..5) {
                Log.d(TAG,"Inner code i : $i on Thread : " + Thread.currentThread().name);
            }
        }
    }

এই ফলাফলগুলি:

10806-10806/com.example.viewmodelapp I/TAG: Outer code started on Thread : main
10806-10806/com.example.viewmodelapp I/TAG: Outer code resumed on Thread : main
// ---- In this example, main had only 2 lines to execute. So, worker thread logs start only after main thread logs complete
// ---- In some cases, where main has more work to do, the worker thread logs get overlap with main thread logs
10806-10858/com.example.viewmodelapp D/TAG: Inner code started  on Thread : DefaultDispatcher-worker-1 making outer code suspend
10806-10858/com.example.viewmodelapp D/TAG: Inner code i : 1 on Thread : DefaultDispatcher-worker-1
10806-10858/com.example.viewmodelapp D/TAG: Inner code i : 2 on Thread : DefaultDispatcher-worker-1
10806-10858/com.example.viewmodelapp D/TAG: Inner code i : 3 on Thread : DefaultDispatcher-worker-1
10806-10858/com.example.viewmodelapp D/TAG: Inner code i : 4 on Thread : DefaultDispatcher-worker-1
10806-10858/com.example.viewmodelapp D/TAG: Inner code i : 5 on Thread : DefaultDispatcher-worker-1

অ্যাসিঙ্ক এবং ব্যবহারের ক্ষেত্রে অপেক্ষা করুন :

  • যখন আমাদের একাধিক কাজ করতে হবে এবং সেগুলি অন্যের সমাপ্তির উপর নির্ভর করে asyncএবং awaitসহায়তা করবে।
  • উদাহরণস্বরূপ, নীচের কোডে, 2ম্যাসেথড () এবং মাইমেথড 2 () স্থগিত ফাংশন রয়েছে। myMethod2()সম্পূর্ণ সম্পূর্ণ হওয়ার পরে মৃত্যুদন্ড কার্যকর করা উচিত myMethod() বা এর myMethod2() ফলাফলের উপর নির্ভর করে myMethod(), আমরা ব্যবহার করতে পারি asyncএবংawait
  • asyncসমান্তরাল অনুরূপ একটি coroutine শুরু launch। তবে, এটি সমান্তরালভাবে অন্য কর্টিন শুরু করার আগে একটি কর্টিনের জন্য অপেক্ষা করার একটি উপায় সরবরাহ করে।
  • সেই পথে await()asyncএর একটি দৃষ্টান্ত ফেরৎ Deffered<T>। ডিফল্ট জন্য Tহবে Unit। যখন আমাদের কোনও asyncসমাপ্তির জন্য অপেক্ষা করতে হবে , তখন আমাদের সেই উদাহরণটি কল .await()করা দরকার । নীচের উদাহরণের মতো, আমরা কল করেছি যা সূচিত করে যে মৃত্যুদণ্ড কার্যকর না হওয়া পর্যন্ত স্থগিত হয়ে যাবে। আমরা আউটপুট একই পর্যবেক্ষণ করতে পারেন। প্রথম সম্পন্ন হয়েছে, যার ডাকে । এবং তারপরে শুরু হয়, যা কল করেDeffered<T>asyncinnerAsync.await()innerAsyncinnerAsyncmyMethod()async innerAsync2myMethod2()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
        Log.i(TAG,"Outer code started on Thread : " + Thread.currentThread().name);
    
         job = GlobalScope.launch(Dispatchers.Default) {
             innerAsync = async {
                 Log.d(TAG, "Inner code started  on Thread : " + Thread.currentThread().name + " making outer code suspend");
                 myMethod();
             }
             innerAsync.await()
    
             innerAsync2 = async {
                 Log.w(TAG, "Inner code started  on Thread : " + Thread.currentThread().name + " making outer code suspend");
                 myMethod2();
             }
        }
    
        Log.i(TAG,"Outer code resumed on Thread : " + Thread.currentThread().name);
        }
    
    private suspend fun myMethod() {
        withContext(Dispatchers.Default) {
            for(i in 1..5) {
                Log.d(TAG,"Inner code i : $i on Thread : " + Thread.currentThread().name);
            }
        }
    }
    
    private suspend fun myMethod2() {
        withContext(Dispatchers.Default) {
            for(i in 1..10) {
                Log.w(TAG,"Inner code i : $i on Thread : " + Thread.currentThread().name);
            }
        }
    }

এই ফলাফলগুলি:

11814-11814/? I/TAG: Outer code started on Thread : main
11814-11814/? I/TAG: Outer code resumed on Thread : main
11814-11845/? D/TAG: Inner code started  on Thread : DefaultDispatcher-worker-2 making outer code suspend
11814-11845/? D/TAG: Inner code i : 1 on Thread : DefaultDispatcher-worker-2
11814-11845/? D/TAG: Inner code i : 2 on Thread : DefaultDispatcher-worker-2
11814-11845/? D/TAG: Inner code i : 3 on Thread : DefaultDispatcher-worker-2
11814-11845/? D/TAG: Inner code i : 4 on Thread : DefaultDispatcher-worker-2
11814-11845/? D/TAG: Inner code i : 5 on Thread : DefaultDispatcher-worker-2
// ---- Due to await() call, innerAsync2 will start only after innerAsync gets completed
11814-11848/? W/TAG: Inner code started  on Thread : DefaultDispatcher-worker-4 making outer code suspend
11814-11848/? W/TAG: Inner code i : 1 on Thread : DefaultDispatcher-worker-4
11814-11848/? W/TAG: Inner code i : 2 on Thread : DefaultDispatcher-worker-4
11814-11848/? W/TAG: Inner code i : 3 on Thread : DefaultDispatcher-worker-4
11814-11848/? W/TAG: Inner code i : 4 on Thread : DefaultDispatcher-worker-4
11814-11848/? W/TAG: Inner code i : 5 on Thread : DefaultDispatcher-worker-4
11814-11848/? W/TAG: Inner code i : 6 on Thread : DefaultDispatcher-worker-4
11814-11848/? W/TAG: Inner code i : 7 on Thread : DefaultDispatcher-worker-4
11814-11848/? W/TAG: Inner code i : 8 on Thread : DefaultDispatcher-worker-4
11814-11848/? W/TAG: Inner code i : 9 on Thread : DefaultDispatcher-worker-4
11814-11848/? W/TAG: Inner code i : 10 on Thread : DefaultDispatcher-worker-4
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.