January 18, 20215 yr I've been trying to do asynchronous tasks by using osbot's event and setting it as async, and using a runnable class to start a new thread. It seems to work well but I have some questions to ask. How do you pause other tasks or sleep the whole bot while on an async event/thread? Is there a proper way to do garbage collection for these async events/threads? (Seems like you can start/pause them but no proper way to "delete" them. I think this becomes a problem if you stop/start the script many times)
January 18, 20215 yr Hello Jarl Im not an expert on threading at all. but This is how I did it in the past. 58 minutes ago, Jarl said: How do you pause other tasks or sleep the whole bot while on an async event/thread? Thread(){ While(true){ if (notpaused){ do stoof } Sleep(random(500,1500)) } } @Override public void pause() { notpaused =false } @Override public void resume() { notpaused =true } 58 minutes ago, Jarl said: Is there a proper way to do garbage collection for these async events/threads? (Seems like you can start/pause them but no proper way to "delete" them. I think this becomes a problem if you stop/start the script many times) Thread pools. https://www.geeksforgeeks.org/thread-pools-java/ https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html
January 18, 20215 yr You will rarely need threads in scripts. I only use async events to correct API errors, e.g. force event termination for WebWalkEvent which used to take seconds to exit years ago. You should consider all possible approaches before resorting to threading. Threads may be justified as an abstraction of a specific task when you want to prioritize it, e.g. eating, which you decide to apply throughout the entire script and want to immediately stop whatever you were doing in order to eat. Background task; execute for as long as the script is executing; do not stop while random solver is executing or when user pauses the script Thread t = new Thread(() -> { while (getBot().getScriptExecutor().isRunning()) { // code try { Thread.sleep(69); } catch (InterruptedException e) { break; } } }); t.start(); Unknown iteration loop on script thread (do not use unless you can justify the need for this); stop when random solver kicks in or user presses pause/stop; the script executor conditions are added in order to make the pause/stop responsive in the case where the code you are executing catches the InterruptedException raised when they press those buttons; this shouldn't happen because that exception is not supposed to be caught, but adding these conditions prevents it from running forever (client buttons will not respond to clicks) if you want to be sure you don't get the client stuck and have to restart while (condition && getBot().getScriptExecutor().isRunning() && !getBot().getScriptExecutor().isPaused() && !getBot().getScriptExecutor().isSuspended()) { // ... }
January 19, 20215 yr Author @Nbacon@TokenThanks for your responses. I was actually thinking of doing a thread while webwalking or during combat. I understand both your threads would work, but from my experience, I had the main thread and the async thread competing with each other to control the mouse to do their thing. Eventually it works out, I was worried about the weird mouse interactions and something potentially not working. Another thing I was thinking of was potentially using a thread to handle other stuff like chat (good for async since it doesn't control the mouse?) and random events (which needs the mouse). Is there a way to pause everything else instantly, when the thread "detects" something? 23 hours ago, Nbacon said: Thread pools. https://www.geeksforgeeks.org/thread-pools-java/ https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html Thanks for this. A good read, though not very useful for osbot since you would rarely need more than 1 thread. I found it useful elsewhere though. 20 hours ago, Token said: Unknown iteration loop on script thread (do not use unless you can justify the need for this); stop when random solver kicks in or user presses pause/stop; the script executor conditions are added in order to make the pause/stop responsive in the case where the code you are executing catches the InterruptedException raised when they press those buttons; this shouldn't happen because that exception is not supposed to be caught, but adding these conditions prevents it from running forever (client buttons will not respond to clicks) if you want to be sure you don't get the client stuck and have to restart Wouldn't this be similar to pausing the thread on exit/on pause/on resume?
January 19, 20215 yr 1 hour ago, Jarl said: doing a thread while webwalking or during combat This is the thread that I asked for help with amost the same thing. Ill look for the code and come back if i find it.
January 19, 20215 yr Author 2 hours ago, Nbacon said: This is the thread that I asked for help with amost the same thing. That's interesting! I guess we were both thinking of gracefully pausing webwalk to eat/high alch/whatever and then resuming the webwalk immediately after. My naive solution would have been to "sleep" the main thread and continue executing the async thread, but I couldn't find a solution for that. 2 hours ago, Nbacon said: Ill look for the code and come back if i find it. Thanks so much 😀
January 20, 20215 yr Here's a custom webwalk event class that I use to perform actions while walking without delays import org.osbot.rs07.api.map.Position; import org.osbot.rs07.event.WebWalkEvent; import org.osbot.rs07.utility.ConditionalSleep2; public class CustomWebWalk extends WebWalkEvent { private AsyncWalkEvent asyncWalkEvent; public CustomWebWalk(Position position) { super(position); } @Override public void onStart() { asyncWalkEvent = new AsyncWalkEvent(); execute(asyncWalkEvent); } @Override public int execute() throws InterruptedException { if (asyncWalkEvent.isLooping()) { // Async is still looping, dont let the web walker execute return 600; } return super.execute(); } @Override public void onEnd() throws InterruptedException { // End the async event and wait for it to finish asyncWalkEvent.setFinished(); ConditionalSleep2.sleep(5000, asyncWalkEvent::hasCompleted); } } And the action that executes in a separate thread import org.osbot.rs07.api.map.Position; import org.osbot.rs07.event.Event; public class AsyncWalkEvent extends Event { private volatile boolean finished = false; private volatile boolean isLooping = false; public AsyncWalkEvent() { setAsync(); } @Override public int execute() throws InterruptedException { if (canPerformAction()) { // Map destination is far enough away, we can perform some actions isLooping = true; if (shouldDoAction()) { // do action } else { // any other necessary action } isLooping = false; } return 600; } @Override public void onEnd() throws InterruptedException { finished = true; } public boolean isLooping() { return isLooping; } public boolean hasCompleted() { return finished; } private boolean canPerformAction() { // Only allow the actions to start if the map destination is far enough away Position dest = getMap().getDestination(); if (dest == null) return false; int dist = getMap().distance(dest); return dist < 20 && dist > 7; } }
January 20, 20215 yr interface ISOMETHING{ void onStart(); void execute(); void onEnd(); int time(); boolean testAsBoolean(); } public class d { boolean walkwalk(MethodProvider mp,int run, PathPreferenceProfile profile,boolean camera, Area area, ISOMETHING something) { WebWalkEvent walkEvent = new WebWalkEvent(area); walkEvent.setPathPreferenceProfile(profile); walkEvent.setEnergyThreshold(run); walkEvent.setMoveCameraDuringWalking(camera); Event event = new Event() { public void onStart() throws InterruptedException { this.setAsync(); something.onStart(); } public int execute() throws InterruptedException { if ( something.testAsBoolean()){ this.setBlocking();//impotant something.execute(); this.setAsync();//impotant } return something.time(); } public void onEnd() throws InterruptedException { something.onEnd(); } }; mp.execute(event); boolean done = mp.execute(walkEvent).hasFinished(); event.setFinished(); return done; } }
January 20, 20215 yr Author @Camaro @NbaconThanks for your code snippets! Both are interesting approaches and I will put both to the test to see how it really interacts. Sadly, it looks like you cannot do something asynchronously throughout a script, unless you prepare extensively for it which might be too much work. Edited January 20, 20215 yr by Jarl
January 20, 20215 yr 29 minutes ago, Jarl said: . I know how that feels. Im writing a banking thing that I might post. The frist 95% took like 2 hours and the last 80% took like 10+hours... All so I don't have to write banking code ever again..... Edited January 20, 20215 yr by Nbacon
June 5, 20232 yr On 1/20/2021 at 4:30 AM, Camaro said: Here's a custom webwalk event class that I use to perform actions while walking without delays import org.osbot.rs07.api.map.Position; import org.osbot.rs07.event.WebWalkEvent; import org.osbot.rs07.utility.ConditionalSleep2; public class CustomWebWalk extends WebWalkEvent { private AsyncWalkEvent asyncWalkEvent; public CustomWebWalk(Position position) { super(position); } @Override public void onStart() { asyncWalkEvent = new AsyncWalkEvent(); execute(asyncWalkEvent); } @Override public int execute() throws InterruptedException { if (asyncWalkEvent.isLooping()) { // Async is still looping, dont let the web walker execute return 600; } return super.execute(); } @Override public void onEnd() throws InterruptedException { // End the async event and wait for it to finish asyncWalkEvent.setFinished(); ConditionalSleep2.sleep(5000, asyncWalkEvent::hasCompleted); } } And the action that executes in a separate thread import org.osbot.rs07.api.map.Position; import org.osbot.rs07.event.Event; public class AsyncWalkEvent extends Event { private volatile boolean finished = false; private volatile boolean isLooping = false; public AsyncWalkEvent() { setAsync(); } @Override public int execute() throws InterruptedException { if (canPerformAction()) { // Map destination is far enough away, we can perform some actions isLooping = true; if (shouldDoAction()) { // do action } else { // any other necessary action } isLooping = false; } return 600; } @Override public void onEnd() throws InterruptedException { finished = true; } public boolean isLooping() { return isLooping; } public boolean hasCompleted() { return finished; } private boolean canPerformAction() { // Only allow the actions to start if the map destination is far enough away Position dest = getMap().getDestination(); if (dest == null) return false; int dist = getMap().distance(dest); return dist < 20 && dist > 7; } } hey this looks great how would i execute the customwebwalk in my script?
Create an account or sign in to comment