حالة البرنامج التعاوني
تحقّق من حالة البرنامج التعاوني باستخدام coroutine.status: running وsuspended وdead
حالة البرنامج التعاوني درس مجاني في Lua Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Lua Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Lua Academy 4 دروس في المجموع.
حالات الكوروتين الأربع
للكوروتينات أربع حالات ممكنة: معلّق (أُنشئ حديثًا أو نفّذ yield، وينتظر التشغيل)، وقيد التشغيل (ينفذ حاليًا)، وعادي (متوقف مؤقتًا للسماح لكوروتين آخر بالعمل)، ومنتهٍ (انتهى أو حدث فيه خطأ). استعلم عن الحالة باستخدام coroutine.status(co).
local co = coroutine.create(function()
print(coroutine.status(coroutine.running())) -- running
coroutine.yield()
end)
print(coroutine.status(co)) -- suspended
coroutine.resume(co) -- prints: running
print(coroutine.status(co)) -- suspended
coroutine.resume(co)
print(coroutine.status(co)) -- deadحالة «عادي»
يدخل الكوروتين في حالة «عادي» عندما يستأنف كوروتينًا آخر. فهو ليس قيد التشغيل (لأن الكوروتين الآخر هو الذي يعمل)، وليس معلّقًا أيضًا، بل ينتظر حتى ينفذ الكوروتين المستأنَف yield. هذه الحالة نادرة، لكنها مهمة لفهم مخططات الكوروتينات المعقدة.
local inner, outer
inner = coroutine.create(function()
print("outer status:", coroutine.status(outer)) -- normal
coroutine.yield()
end)
outer = coroutine.create(function()
coroutine.resume(inner)
end)
coroutine.resume(outer)
-- prints: outer status: normalالتحقق قبل الاستئناف
تحقّق دائمًا من حالة الكوروتين قبل استئنافه، ولا سيما داخل الحلقات. استئناف كوروتين منتهٍ خطأ. كما أن استئناف كوروتين قيد التشغيل خطأ أيضًا، لأنه قد يؤدي إلى استدعاء تكراري لا نهائي.
local function safeResume(co, ...)
local status = coroutine.status(co)
if status == "dead" then
return false, "cannot resume dead coroutine"
end
if status == "running" then
return false, "cannot resume running coroutine"
end
return coroutine.resume(co, ...)
endالحالة بعد حدوث خطأ
عندما يرفع جسم الكوروتين خطأً غير معالَج، يعيد coroutine.resume القيمة false ورسالة الخطأ. وينتقل الكوروتين إلى الحالة «منتهٍ». ولا يمكن إعادة تشغيله؛ لذا يجب إنشاء كوروتين جديد إذا أردت إعادة المحاولة.
local co = coroutine.create(function()
error("something went wrong")
end)
local ok, err = coroutine.resume(co)
print(ok, err) -- false ...: something went wrong
print(coroutine.status(co)) -- dead
-- Cannot resume dead coroutine:
local ok2, err2 = coroutine.resume(co)
print(ok2, err2) -- false cannot resume dead coroutinecoroutine.isyieldable
تعيد coroutine.isyieldable() القيمة true إذا كان الكوروتين قيد التشغيل يستطيع تنفيذ yield. وتعيد القيمة false في الخيط الرئيسي وفي دوال C التي لا تدعم yield. تحقّق دائمًا قبل تنفيذ yield إذا لم تكن متأكدًا من السياق.
local co = coroutine.create(function()
print("isyieldable:", coroutine.isyieldable()) -- true
coroutine.yield()
end)
coroutine.resume(co)
-- In main thread:
print("isyieldable:", coroutine.isyieldable()) -- false
-- coroutine.yield() -- ERROR in main threadمراقبة مجموعة من الكوروتينات
تتبّع مجموعة من الكوروتينات، وأزل الكوروتينات المنتهية بعد كل جولة من عمليات الاستئناف. وهذا هو الأساس الذي يُبنى عليه مجدول المهام.
local function makeWorker(n, name)
return coroutine.create(function()
for i = 1, n do
print(name, "step", i)
coroutine.yield()
end
end)
end
local workers = {
makeWorker(2, "fast"),
makeWorker(4, "slow"),
}
while #workers > 0 do
local alive = {}
for _, co in ipairs(workers) do
coroutine.resume(co)
if coroutine.status(co) ~= "dead" then
alive[#alive+1] = co
end
end
workers = alive
endتصحيح أخطاء الكوروتينات
استخدم عمليات التحقق من الحالة لمراقبة الشيفرة المعتمدة على الكوروتينات وتصحيح أخطائها. اطبع انتقالات الحالة لفهم مسار التنفيذ. وفي الأنظمة المعقدة، أسند أسماء إلى الكوروتينات عبر جدول تغليف لتحسين مخرجات تصحيح الأخطاء.
local function namedCo(name, fn)
local co = coroutine.create(fn)
return {
co = co,
name = name,
resume = function(self, ...)
print("[" .. self.name .. "] resume")
local results = table.pack(coroutine.resume(self.co, ...))
print("[" .. self.name .. "] status: " .. coroutine.status(self.co))
return table.unpack(results, 1, results.n)
end
}
end
local worker = namedCo("worker1", function()
coroutine.yield()
end)
worker:resume()
worker:resume()إعادة تشغيل الكوروتينات المنتهية
بمجرد أن يصبح الكوروتين منتهيًا، لا يمكن استئنافه. ولـ«إعادة تشغيله»، يجب إنشاء كوروتين جديد من الدالة نفسها. ومن الأنماط الشائعة استخدام مصنع ينشئ كوروتين جديدًا عند الطلب.
local function makeCounter(start, step)
return coroutine.wrap(function()
local n = start or 0
while true do
coroutine.yield(n)
n = n + (step or 1)
end
end)
end
local count = makeCounter(0, 2)
for i = 1, 5 do io.write(count() .. " ") end
print() -- 0 2 4 6 8
-- "Restart" by creating a new one
count = makeCounter(100)
print(count()) -- 100سلوك الأخطاء في Coroutine.wrap
عندما يحدث خطأ في كوروتين مغلّف، ينتشر الخطأ خارج استدعاء دالة التغليف. وعلى خلاف coroutine.resume الذي يعيد false+error، ترفع الدوال التي يعيدها wrap الخطأ مباشرةً. استخدم pcall حول استدعاءات wrap إذا كنت بحاجة إلى التقاط الأخطاء.
local gen = coroutine.wrap(function()
coroutine.yield(1)
error("oops")
coroutine.yield(2) -- never reached
end)
print(gen()) -- 1 (ok)
local ok, err = pcall(gen)
print(ok, err) -- false ...: oops
-- Subsequent call: dead coroutine
ok, err = pcall(gen)
print(ok, err) -- false cannot resume dead coroutineisyieldable مقابل status
هناك طريقتان لفحص سياق الكوروتين: تعطي coroutine.status(co) حالة كوروتين محدد، بينما تخبرك coroutine.isyieldable() بما إذا كان سياق التنفيذ الحالي يستطيع تنفيذ yield. استخدم status للتحقق من الكوروتينات الأخرى، واستخدم isyieldable للتحقق من إمكانية تنفيذ yield بأمان.
local function maybeYield()
if coroutine.isyieldable() then
coroutine.yield()
else
-- in main thread or non-yieldable context
print("cannot yield here")
end
end
maybeYield() -- prints "cannot yield here" (main thread)
local co = coroutine.create(maybeYield)
coroutine.resume(co) -- yields successfullyاختبار سريع
ما الحالة التي يدخل فيها الكوروتين عند انتهاء تنفيذ دالة جسمه؟
مراجعة: حالة الكوروتين
الملخص:
- الحالات: معلّق ← قيد التشغيل ↔ عادي ← منتهٍ
- يعيد
coroutine.status(co)سلسلة الحالة - منتهٍ = انتهى التنفيذ أو حدث خطأ؛ ولا يمكن استئنافه
- يتحقق
coroutine.isyieldable()مما إذا كان السياق الحالي يستطيع تنفيذ yield - تحقّق دائمًا من الحالة قبل الاستئناف داخل الحلقات
- تنتشر أخطاء wrap مباشرةً؛ بينما يعيد resume القيمة false+err
الأسئلة الشائعة
هل درس «حالة البرنامج التعاوني» مجاني؟
نعم — نص درس «حالة البرنامج التعاوني» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Lua Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Lua Academy 4 دروس في المجموع.
ماذا ستتعلم في «حالة البرنامج التعاوني»؟
تحقّق من حالة البرنامج التعاوني باستخدام coroutine.status: running وsuspended وdead تتمرن على Lua Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Lua Academy؟
لا تُشترط خبرة سابقة. Lua Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «حالة البرنامج التعاوني»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Lua Academy هذا؟
نعم. كل درس في Lua Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- إنشاء البرامج التعاونية
- resume وyield
- حالة البرنامج التعاوني
- نمط المنتج والمستهلك