Lua Academy · Lektion

Oprettelse af coroutiner

Opret coroutiner med coroutine.create og coroutine.wrap.

Lektion 1 af 412 trin

Oprettelse af coroutiner er en gratis Lua Academy-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Lua Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Lua Academy-kurset indeholder 4 lektioner i alt.

Hvad er en coroutine?

En coroutine er en funktion, der kan sætte sin udførelse på pause (yield) og senere fortsætte fra det sted, hvor den slap. I modsætning til tråde er coroutiner samarbejdende – kun én kører ad gangen, og de afgiver eksplicit kontrollen. Lua-coroutiner har deres egen stack og lokale variabler.

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)          -- resumed

coroutine.create kontra coroutine.wrap

coroutine.create(fn) opretter en coroutine og returnerer et coroutine-objekt (typen thread). coroutine.wrap(fn) opretter en coroutine og returnerer en funktion, der genoptager den, når den kaldes. wrap er enklere, men skjuler coroutine-objektet.

-- 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-livscyklus

En coroutine har fire tilstande: suspenderet (kører ikke), kører (udføres i øjeblikket), død (returneret eller med en fejl) og normal (sat på pause, fordi den genoptog en anden coroutine). Kontrollér tilstanden med 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

Kørsel af flere coroutiner

Opret flere coroutiner, og flet deres kørsel ved at genoptage dem på skift. Det simulerer samtidig udførelse (samarbejdende multitasking). Hver coroutine bevarer sin egen tilstand mellem yield-kald.

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

Iteration med coroutine.wrap

coroutine.wrap bruges ofte til at oprette iteratorer. Den returnerede funktion kaldes, hver gang iteratoren går videre. Når coroutine-kroppen afsluttes, udløser funktionen en fejl – brug pcall, eller kontrollér tilstanden, hvis det er nødvendigt.

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

Fejl i coroutiner

Hvis en coroutine udløser en fejl, returnerer coroutine.resume false efterfulgt af fejlmeddelelsen. Coroutinen skifter til tilstanden dead. En død coroutine kan ikke genoptages igen.

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-identitet

coroutine.running() returnerer den coroutine, der kører i øjeblikket, samt en boolesk værdi, der angiver, om den er hovedtråden. Brug dette inde i en coroutine for at få en reference til den selv.

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

Uendelig generator

En coroutine-krop kan indeholde en uendelig løkke med yield-kald – generatoren producerer værdier efter behov uden at afslutte. Dette er et vigtigt anvendelsesområde: dovne, uendelige sekvenser.

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 8

Coroutiner som opgaver

En grundlæggende opgaveplanlægger: gem coroutiner i en kø, og genoptag dem på skift. Når en coroutine udfører yield, sættes den tilbage i køen. Når den dør, fjernes den. Dette er en minimal samarbejdende planlægger.

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()

Coroutinehukommelse

Hver coroutine har sin egen stak. Stakke kan blive store ved dybe kaldkæder. I scenarier med høje ydeevnekrav bør du undgå at oprette tusindvis af coroutiner, der er aktive samtidig. Genbrug coroutiner, når det er muligt, eller brug puljer.

-- 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")

Hurtigt tjek

Hvilken tilstand er en coroutine i umiddelbart efter coroutine.create(fn)?

Opsummering: Oprettelse af coroutiner

Opsummering:

  • coroutine.create(fn) → coroutine-objekt; wrap(fn) → funktion, der kan genoptages
  • Tilstande: suspenderet → kører → suspenderet/død
  • coroutine.resume(co, ...) starter eller genoptager
  • Fejl under genoptagelse: false + fejlmeddelelse; coroutine → død
  • Uendelige generatorer via while true do yield() end
  • Bruges til kooperativ multitasking og dovne sekvenser
Gratis at komme i gang

Lær Lua med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
40
Lektioner
159

Ofte stillede spørgsmål

Er lektionen “Oprettelse af coroutiner” gratis?

Ja — alle 3 lektioner i læringssporet Lua Academy, inklusive “Oprettelse af coroutiner”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Lua Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Oprettelse af coroutiner”?

Opret coroutiner med coroutine.create og coroutine.wrap. Du øver dig i Lua Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Lua Academy?

Der kræves ingen tidligere erfaring. Lua Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.

Hvor lang tid tager lektionen “Oprettelse af coroutiner”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Lua Academy-lektion?

Ja. Alle Lua Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Oprettelse af coroutiner
  2. resume og yield
  3. Coroutine-status
  4. Producer-forbruger-mønster
← Tilbage til Lua Academy