This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
samken600's profile picture

[Question][Lua] How do you run a function in the background of a program?

Started by samken600, 24 May 2013 - 11:22 AM
samken600 #1
Posted 24 May 2013 - 01:22 PM
OK so I wrote this code but I want it to constantly run detectcycle() in the background all the time while doing the main program
Is this possible and if so how?
Please let me know if I have not been clear enough


m = peripheral.wrap("top")
m.setTextColor(colors.cyan)
function changeColour(new)
    m.setBackgroundColour(new)
m.clear()
m.setCursorPos(1,1)
end
function detectcycle()
    if rs.getInput("back") == false then
	 m.setCursorPos(1,5)
	 m.clearLine()
	 m.write("InCycle")
  sleep(0)
else
	 m.setCursorPos(1,5)
  m.clearLine()
  m.write("Done")
  sleep(0)
end
end
function text(onoff, tf)
    m.setCursorPos(1,1)
    m.write("Quarry")
m.setCursorPos(1,2)
m.write("Control")
m.setCursorPos(1,3)
m.write("State:")
m.setCursorPos(1,4)
m.write(onoff)
m.setCursorPos(1,5)
rs.setOutput("left", tf)
    sleep(2.5)
detectcycle()
end

function waitTouch()
    os.pullEvent("monitor_touch")
end
while true do
    sleep(0)
changeColour(colors.red)
    text("OFF", false)
    waitTouch()
changeColour(colors.green)
    text("ON", true)
    waitTouch()
end
SuicidalSTDz #2
Posted 24 May 2013 - 02:57 PM
Read up on the parallel api on the wiki. This is the solution to your problem, as are coroutines. However, coroutines are far harder to use for a beginner - so stay away from them. If you need further help or an explanation, feel free to ask.
samken600 #3
Posted 24 May 2013 - 03:00 PM
Thank you. Reading up on them now. I had heard of and looked at coroutines but they really confused me and I didn't really understand what they did so will have a look at this
Lyqyd #4
Posted 24 May 2013 - 03:03 PM
Parallel is simply a coroutine manager. They aren't different things; you're still "using coroutines".
SuicidalSTDz #5
Posted 24 May 2013 - 03:15 PM
So pretty much, this is your setup:

local function foo()
 while true do
  --someStuff
 end
end

local function fooTwo()
 while true do
  --someStuff
 end
end

parallel.waitForAny(foo, fooTwo)

Note: We do not need closing parenthesis to indicate a call.
Note: We cannot call functions with arguments as we usually do. We must use a function to house the called function with arguments:
parallel.waitForAny(function() foo("test") end, fooTwo)
samken600 #6
Posted 24 May 2013 - 03:31 PM
OK I have just played around with it a bit and I don't see an easy way to make it work with my code. I want them both continuously running at the same time, which parallel.waitForAny() or parallel.waitForAll() can't do. I want them working completely separately, if you know what I mean, so they don't affect each other
Lyqyd #7
Posted 24 May 2013 - 05:38 PM
No, we don't know what you mean, or why that wouldn't work for you. What are you actually trying to accomplish?
Yevano #8
Posted 24 May 2013 - 05:49 PM
OK I have just played around with it a bit and I don't see an easy way to make it work with my code. I want them both continuously running at the same time, which parallel.waitForAny() or parallel.waitForAll() can't do. I want them working completely separately, if you know what I mean, so they don't affect each other

As long as they both continuously call yielding functions (such as os.pullEvent or coroutine.yield), the functions should run together without affecting each other.
SuicidalSTDz #9
Posted 24 May 2013 - 06:02 PM
I actually see no use of the parallel api in this script, but here is my version:


m = peripheral.wrap("top")
m.setTextColor(colors.cyan)

local function changeColour(new)
  m.setBackgroundColour(new)
  m.clear()
  m.setCursorPos(1,1)
end

local function detectcycle()
  if not rs.getInput("back") then --the logical operator 'not' is the same as ' == false '
	m.setCursorPos(1,5)
	m.clearLine()
	m.write("InCycle")
	sleep(0)
  else
	m.setCursorPos(1,5)
	m.clearLine()
	m.write("Done")
	sleep(0)
  end
end

local function text(onoff, tf) -- '\n' will make a new line for you, no need for setting the cursorPos
  m.setCursorPos(1,1)
  m.write("Quarry\n")
  m.write("Control\n")
  m.write("State:\n")
  m.write(onoff.."\n")
  rs.setOutput("left", tf)
  sleep(2.5)
  detectcycle()
end

local foo = true

while true do
  local ev, p1, x, y = os.pullEvent("monitor_touch")
  if foo then
    changeColour(colors.red)
    text("OFF", false)
    foo = false
  else
    changeColour(colors.green)
    text("ON", true)
    foo = true
  end
end
samken600 #10
Posted 24 May 2013 - 06:05 PM
Sorry for being unclear. I think yevano knows what I mean but one of them I want to activate when I touch the monitor, so it is not continuously yielding an event. Is there any way round that or do I not understand it properly?
And SuicidalSTDz, I know about the \n thing but it was coming up with a question mark when I printed it onto a monitor and that's not what I want. I wan't it constantly checking if it's receiving a redstone signal from the back and if it changes edit the last line at the same time as running the main script (the while true do one).
Except for that everything works
SuicidalSTDz #11
Posted 24 May 2013 - 06:10 PM
while true do
 local _, p1, x, y = os.pullEvent("monitor_touch") --this will not yield until you touch the screen
 --runCycle - run the cycle every time the monitor_touch event is fired
end

I still see no need for the parallel api. Unless you want to integrate another program into the script.
samken600 #12
Posted 24 May 2013 - 06:21 PM
The reason for using it is can take up to 20 seconds for the thing it is sending the signal too to complete it's cycle and update the redstone signal on the back so I want that to be constantly updated
Lyqyd #13
Posted 25 May 2013 - 12:31 AM
So, you basically just want to handle redstone and monitor_touch events?


while true do
  local e, p1, p2, p3 = os.pullEvent()
  if e == "redstone" then
    --handle redstone changes
  elseif e == "monitor_touch" then
    --handle monitor touches
  end
end