Advertisement
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

[New API] Return value from AsyncTask

Comments in 'Plugin Development' started by Adaasi, Dec 6, 2014.

  1. Adaasi
    Offline

    Adaasi Active Member

    Joined:
    Aug 14, 2014
    Posts:
    80
    How can I return a value from AsyncTask class?
    This is my code:
    Start.php (Main Class)
    PHP:
    //enable event
    public function onEnable(){
       
    $return $this->getServer()->getScheduler()->scheduleAsyncTask(new Async("test"));
       print(
    $return);
    }
    Async.php (AsyncTask Class)
    PHP:
    namespace Example;

    use 
    pocketmine\scheduler\AsyncTask;

    class 
    Async extends AsyncTask{
       public function 
    __construct($var){
           
    $this->var $var;
       }
       
       public function 
    onRun(){
          return 
    $this->var;
       }
    }
  2. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,325
    Plugins:
    11
    Minecraft User:
    PEMapModder
    @Adaasi an AsyncTask is run at another thread. The time it gets finished is undefined. The reason for making an AsyncTask is to make it not blocking the main thread (i.e. let things be run at, like, another process, but we call it a "thread" instead). As I said, PHP doesn't execute any code until your current line finishes executing. scheduleAsyncTask submits the AsyncTask to the scheduler pool and PocketMine will start them at another thread. You can use $this->setResult($result) in onRun() to store the result (must be serializable, like strings, arrays, numbers, etc.) and get the result with $this->getResult() in onCompletion(Server $server) inside the AsyncTask, which is run at the main thread.

    Principle:
    You submit the AsyncTask to ServerScheduler.
    PocketMine tells pthreads to start another thread to run your AsyncTask. We don't know when the system starts executing the task, and we don't know when each call in your task is run. It might become that the task runs one line, then PocketMine runs another line, etc., so do not interact
    The code below scheduleAsyncTask() gets run, returns, and PocketMine finishes the rest of this tick.
    Every tick afterwards, PocketMine checks if your task ended. If it does, it will call your onCompletion() method from ServerScheduler.php. So it actually schedules onCompletion() to be run later.
  3. Adaasi
    Offline

    Adaasi Active Member

    Joined:
    Aug 14, 2014
    Posts:
    80
    OK, but isn't there any way to return a value in onCompletion() event?
    PHP:
    namespace Example;

    use 
    pocketmine\scheduler\AsyncTask;
    use 
    pocketmine\Server;

    class 
    Async extends AsyncTask{
     public function 
    __construct($var){$this->var $var;
     }
     
     public function 
    onCompletion(Server $server){
     return 
    $this->var;
     }
    }
  4. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,325
    Plugins:
    11
    Minecraft User:
    PEMapModder
    As I said, onCompletion() is run at another tick. Do you return a value in a scheduled task?

    Moreover, the purpose of using threads is to let things run outside the main thread. To get the return value, PHP must first finish executing yoru task. How can you return a value before the task finished executing?
    If you want to wait until the task executing, then you are blocking the main thread. Then what is the purpoes of starting another thread?
  5. Adaasi
    Offline

    Adaasi Active Member

    Joined:
    Aug 14, 2014
    Posts:
    80
    no, it seems to return null
  6. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,325
    Plugins:
    11
    Minecraft User:
    PEMapModder
    null means nothing is returned.
    Look at the edited post.
  7. Adaasi
    Offline

    Adaasi Active Member

    Joined:
    Aug 14, 2014
    Posts:
    80
    Yes. It returns nothing
  8. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,325
    Plugins:
    11
    Minecraft User:
    PEMapModder
    Look at the edited post. onRun() is run at the background, but while it is running at the background you need to let the foreground go on. If the main thread (foreground) is stuck at waiting at the AsyncTask (background), the server will be "overloaded" and this is unacceptable in plugins.
  9. Adaasi
    Offline

    Adaasi Active Member

    Joined:
    Aug 14, 2014
    Posts:
    80
    Do you remember the DownloadFile plugin? I need to return value from AsyncTask to know from the main code if the download is done or if it has encountered errors
  10. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,325
    Plugins:
    11
    Minecraft User:
    PEMapModder
    Say, it takes 10 seconds to download the file. In this ten seconds, PocketMine has to do other things, such as to handle new packets from players. So, we start an AsyncTask to download the file at background. Of course download is not completed when you just started the AsyncTask and are running the next line, because the next line is run instantly before your download finished.
    You call scheduleAsyncTask().
    -> This call tells PocketMine to start another thread for your (download) task. Assume it will take 10 seconds long to download.
    -> PocketMine tells PHP to run your onRun() function in the background and exits back to your function to execute the next line.
    You run the line after scheduleAsyncTask(). At the same time (technically it isn't at the same time, but you should assume it at the same time until you learn about thread synchronization), PHP is running your onRun() function at the background. It is running in progress, so it is impossible to get a return value from it.
    Your function exits. If your function is normal, it doesn't take 10 seconds to exit your function. At the same time, your onRun() function is still running in progress.
    PocketMine continues to run other code for that tick, then it will go on other ticks. It is possible that your function gets called again. But your onRun() function is still running in progress.
    One day tick, PocketMine scheduler checks your thread and found that your onRun() function is finally completed! So, happily, PocketMine calls the onCompletion() function of your AsyncTask to tell you that it finished.
    If you still don't understand, search online about threading. I am not a good teacher to explain all that concept.
  11. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,325
    Plugins:
    11
    Minecraft User:
    PEMapModder
    Or, to explain with a story:
    One day, a man is working in a restaurant to treat the customers. (PocketMine normal code)
    A customer told the man he wanted a cup of tea. (your function gets called)
    The man needed to stay to treat the customers, (PocketMine needs to stay alive to respond to the clients and not overload)
    so he sent a worker to make a cup of tea. (start a new thread/AsyncTask to do something)
    While the worker is making the tea, (while your new thread is doing something)
    the man finished talking to this customer (your function exits)
    and treated other customers. (PocketMine runs other code)
    Every while, (every tick)
    the man looked at the worker to see if the tea is made. (PocketMine checks if your AsyncTask is finished)
    Remember that when the tea is still not made, the man and the worker have to cooperate (thread synchronization). If they don't, they may do the same thing to the same customer twice (thread race conditions). Therefore, let the man do everything. (Don't call PocketMine API functions from other threads/AsyncTasks)
    Finally, once, the man found that the tea is made. (ServerScheduler finds that the AsyncTask is finished)
    So the man took the tea from the worker (PocketMine calls your onCompletion() function)
    and gave it to the customer. (your onCompletion() function runs)
    Then the worker is now killed fired back standby (would've been more alike to the analogy if he is fired, as well as to warn you not to start too many threads). (Your AsyncTask will be collected because it is finished)
    Then the man continues to do other things.
  12. iksaku
    Offline

    iksaku Notable Member Plugin Developer

    Joined:
    Sep 2, 2013
    Posts:
    1,132
    Plugins:
    4
    Minecraft User:
    iksaku
    Now I understand better the usage of AsyncTasks! :3
    Creeperface likes this.
  13. EvolSoft
    Offline

    EvolSoft Notable Member Plugin Developer

    Joined:
    Sep 10, 2014
    Posts:
    821
    Plugins:
    15
    Minecraft User:
    Flavius12
    Nice :D

Share This Page

Advertisement