การสร้างโคโรทีน
สร้างโคโรทีนด้วย coroutine.create และ coroutine.wrap
การสร้างโคโรทีน เป็นบทเรียน Lua Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Lua Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Lua Academy มีบทเรียนทั้งหมด 4 บทเรียน
Coroutine คืออะไร
coroutine คือฟังก์ชันที่สามารถหยุดการทำงาน (yield) และกลับมาทำงานต่อจากจุดเดิมได้ในภายหลัง ต่างจากเธรด coroutine ทำงานแบบ ร่วมมือกัน โดยจะมีเพียงหนึ่งตัวที่ทำงานในแต่ละครั้ง และแต่ละตัวต้องคืนการควบคุมอย่างชัดเจน coroutine ของ Lua มีสแตกและตัวแปร local เป็นของตัวเอง
local co = coroutine.create(function()
print("start")
coroutine.yield()
print("resumed")
coroutine.yield()
print("done")
end)
print(coroutine.status(co)) -- suspended
coroutine.resume(co) -- start
print(coroutine.status(co)) -- suspended
coroutine.resume(co) -- resumedcoroutine.create เทียบกับ coroutine.wrap
coroutine.create(fn) สร้าง coroutine และส่งคืนออบเจ็กต์ coroutine (ชนิด thread) ส่วน coroutine.wrap(fn) สร้าง coroutine และส่งคืนฟังก์ชันที่เมื่อถูกเรียกใช้จะทำงานต่อ ฟังก์ชัน wrap ใช้งานง่ายกว่า แต่จะซ่อนออบเจ็กต์ coroutine
-- create: returns coroutine object
local co = coroutine.create(function(x)
return x * 2
end)
local ok, val = coroutine.resume(co, 5)
print(ok, val) -- true 10
-- wrap: returns a resumable function
local gen = coroutine.wrap(function(x)
return x * 3
end)
print(gen(5)) -- 15วงจรชีวิตของ Coroutine
coroutine มีสถานะสี่แบบ ได้แก่ suspended (ไม่ได้ทำงาน), running (กำลังทำงาน), dead (ส่งคืนผลลัพธ์หรือเกิดข้อผิดพลาด) และ normal (หยุดชั่วคราวเพราะกลับไปทำงานต่อใน coroutine อื่น) ตรวจสอบสถานะได้ด้วย coroutine.status(co)
local co = coroutine.create(function()
coroutine.yield()
end)
print(coroutine.status(co)) -- suspended
coroutine.resume(co) -- runs until yield
print(coroutine.status(co)) -- suspended again
coroutine.resume(co) -- runs until end
print(coroutine.status(co)) -- deadการเรียกใช้ Coroutine หลายตัว
สร้าง coroutine หลายตัว แล้วสลับการทำงานระหว่างกันโดยเรียกให้แต่ละตัวทำงานต่อทีละตัว วิธีนี้จำลองการทำงานพร้อมกัน (การทำงานหลายอย่างแบบร่วมมือกัน) coroutine แต่ละตัวจะเก็บสถานะของตัวเองไว้ระหว่างการ yield
local function worker(name, steps)
for i = 1, steps do
print(name .. ": step " .. i)
coroutine.yield()
end
end
local co1 = coroutine.create(function() worker("A", 3) end)
local co2 = coroutine.create(function() worker("B", 3) end)
for _ = 1, 3 do
coroutine.resume(co1)
coroutine.resume(co2)
end
-- A:1, B:1, A:2, B:2, A:3, B:3การวนซ้ำด้วย coroutine.wrap
coroutine.wrap มักใช้สร้างตัววนซ้ำ ฟังก์ชันที่ส่งคืนมาจะถูกเรียกทุกครั้งที่ตัววนซ้ำเลื่อนไปยังค่าถัดไป เมื่อส่วนการทำงานของ coroutine สิ้นสุดลง ฟังก์ชันจะทำให้เกิดข้อผิดพลาด หากจำเป็น ให้ใช้ pcall หรือตรวจสอบสถานะ
local function range(n)
return coroutine.wrap(function()
for i = 1, n do
coroutine.yield(i)
end
end)
end
for v in range(5) do
io.write(v .. " ")
end
print() -- 1 2 3 4 5ข้อผิดพลาดใน Coroutine
หาก coroutine ทำให้เกิดข้อผิดพลาด coroutine.resume จะส่งคืน false ตามด้วยข้อความแสดงข้อผิดพลาด coroutine จะเปลี่ยนไปเป็นสถานะ dead และไม่สามารถเรียกให้ทำงานต่อได้อีก
local co = coroutine.create(function(x)
if x < 0 then error("negative input: " .. x) end
return math.sqrt(x)
end)
local ok, val = coroutine.resume(co, -1)
print(ok, val) -- false input:2: negative input: -1
print(coroutine.status(co)) -- dead
-- Can't resume a dead coroutine:
ok, val = coroutine.resume(co)
print(ok, val) -- false cannot resume dead coroutineข้อมูลประจำตัวของ Coroutine
coroutine.running() ส่งคืน coroutine ที่กำลังทำงานอยู่ในขณะนั้นและค่าบูลีนที่ระบุว่าเป็นเธรดหลักหรือไม่ ใช้คำสั่งนี้ภายใน coroutine เพื่อรับข้อมูลอ้างอิงถึงตัวมันเอง
local co = coroutine.create(function()
local self, isMain = coroutine.running()
print("type:", type(self)) -- thread
print("isMain:", isMain) -- false
print("status:", coroutine.status(self)) -- running
end)
coroutine.resume(co)
-- In main thread:
local main, isMain = coroutine.running()
print("main isMain:", isMain) -- trueตัวสร้างแบบไม่สิ้นสุด
ส่วนการทำงานของ coroutine สามารถมีลูปที่ทำงานไม่สิ้นสุดและมี yield อยู่ภายในได้ ตัวสร้างจะสร้างค่าตามต้องการโดยไม่สิ้นสุดการทำงาน นี่คือกรณีการใช้งานสำคัญสำหรับลำดับข้อมูลแบบล่าช้าที่มีจำนวนไม่สิ้นสุด
local function naturals(start)
return coroutine.wrap(function()
local n = start or 1
while true do
coroutine.yield(n)
n = n + 1
end
end)
end
local gen = naturals(1)
for i = 1, 8 do
io.write(gen() .. " ")
end
print() -- 1 2 3 4 5 6 7 8Coroutine ในฐานะงาน
ตัวจัดตารางงานพื้นฐานสามารถเก็บ coroutine ไว้ในคิวและเรียกให้แต่ละตัวทำงานต่อทีละตัว เมื่อ coroutine ทำการ yield ให้นำกลับเข้าไปในคิว เมื่อสิ้นสุดการทำงานแล้วให้นำออก นี่คือตัวจัดตารางงานแบบร่วมมือกันที่มีโครงสร้างขั้นต่ำ
local tasks = {}
local function spawn(fn)
tasks[#tasks+1] = coroutine.create(fn)
end
local function run()
while #tasks > 0 do
local alive = {}
for _, co in ipairs(tasks) do
coroutine.resume(co)
if coroutine.status(co) ~= "dead" then
alive[#alive+1] = co
end
end
tasks = alive
end
end
spawn(function() for i=1,3 do print("T1:"..i); coroutine.yield() end end)
spawn(function() for i=1,3 do print("T2:"..i); coroutine.yield() end end)
run()หน่วยความจำของโครูทีน
โครูทีนแต่ละตัวมีสแตกเป็นของตัวเอง สแตกอาจมีขนาดใหญ่ขึ้นเมื่อมีการเรียกซ้อนกันหลายระดับ ในสถานการณ์ที่ต้องการประสิทธิภาพสูง ควรหลีกเลี่ยงการสร้างโครูทีนหลายพันตัวที่ทำงานอยู่พร้อมกัน หากเป็นไปได้ ให้ใช้โครูทีนซ้ำหรือใช้พูล
-- Coroutine pool concept
local pool = {}
local function getCoroutine(fn)
-- Reuse dead coroutine slots
for i, co in ipairs(pool) do
if coroutine.status(co) == "dead" then
pool[i] = coroutine.create(fn)
return pool[i]
end
end
local co = coroutine.create(fn)
pool[#pool+1] = co
return co
end
print("Pool pattern for coroutine reuse")ตรวจสอบความเข้าใจอย่างรวดเร็ว
โครูทีนอยู่ในสถานะใดทันทีหลังจาก coroutine.create(fn)?
สรุป: การสร้างโครูทีน
สรุป:
coroutine.create(fn)→ ออบเจ็กต์โครูทีน;wrap(fn)→ ฟังก์ชันที่ดำเนินการต่อได้- สถานะ: ถูกพัก → กำลังทำงาน → ถูกพัก/สิ้นสุด
coroutine.resume(co, ...)ใช้เริ่มต้นหรือดำเนินการต่อ- ข้อผิดพลาดระหว่างการดำเนินการต่อ: false + ข้อความข้อผิดพลาด; โครูทีน → สิ้นสุด
- ตัวสร้างแบบไม่สิ้นสุดผ่าน
while true do yield() end - ใช้สำหรับการทำงานหลายงานแบบร่วมมือกันและลำดับแบบประเมินค่าเมื่อจำเป็น
คำถามที่พบบ่อย
บทเรียน “การสร้างโคโรทีน” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การสร้างโคโรทีน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Lua Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Lua Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การสร้างโคโรทีน”
สร้างโคโรทีนด้วย coroutine.create และ coroutine.wrap คุณปฏิบัติ Lua Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Lua Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Lua Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “การสร้างโคโรทีน” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Lua Academy นี้ได้ไหม
ได้ บทเรียน Lua Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การสร้างโคโรทีน
- resume และ yield
- สถานะโคโรทีน
- รูปแบบผู้ผลิต-ผู้บริโภค