简体   繁体   中英

Multithreading / asynchronously in Php codeigniter

In my controller I load the HTML using view. Now before the view loads, I need to call 2 more functions. So what happens is, it waits for the function 1 to finish (5-6 seconds) and then 2nd function to finish (another 5-6 seconds) and the view loads. is it possible to run both the functions together so that the view can run faster

 public function index() { $empid = "12345"; //running function / step / process / one $this->function1($empid); //running function / step / process / two $this->function2($empid); $this->load->view("welcome",$data); } 

The answer is to use PHP's exec() function. ( Read about exec() and more info here .) This can be implemented a couple of ways:

  1. Create a standalone php file that will be executed.
  2. Create a Controller that will be executed.

Option 1 can be very light-weight as you only need to create a php file with the code you want to run. But it won't have access to Codeigniter libraries. If you do need/want to use CI within the "process" then Option 2 is what you want.

I will show how to implement option 2. This utilizes Codeigniter's ability to be run from the command line (CLI). ( Read about that here. ) We will emulate that functionality by using exec() .

This is setup to prove the functions get called and work. They basically run some time-consuming tasks a lot of times so we can actually see that the browser is blocked while they execute.

Create a controller with methods to be called through exec() and put it in application/controllers .

Tools.php

class Tools extends CI_Controller
{
    public function proc1($param = 1)
    {
        $time_start = microtime(true);
        for($i = 1; $i < $param ; $i++)
        {
            sqrt($i);
        }
        $time_end = microtime(true);
        $time = $time_end - $time_start;
        $iters = number_format($param);
        echo "Proc1 calculated $iters square roots in $time seconds\n";
    }

    public function proc2($param = 1)
    {
        $time_start = microtime(true);
        for($i = 1; $i < $param; $i++)
        {
            log10 ($i);
        }
        $time_end = microtime(true);
        $time = $time_end - $time_start;
        $iters = number_format($param);
        echo "Proc2 calculated $iters Base-10 logarithms in $time seconds\n";
    }

}

Here is the controller that will make the calls to exec() .

class Proc_test extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();
    }

    public function index()
    {
        echo "Index is running<br>";
        $param = 5000000;
        $command = "php ".FCPATH."index.php tools proc1 $param";
        $out = [];
        exec($command, $out);
        var_dump($out);

        $command = "php ".FCPATH."index.php tools proc2 $param";
        $out = [];
        exec($command, $out);
        var_dump($out);

        echo "Procs have been called";
    }
}

Make the call to the new controller eg ` http://example.com/proc_test

With $param set to 5-million it takes my system a bit over 8 seconds to show the result. Try it a few times changing the value of $param to see different results.

Obviously, we don't want the browser to block. That is fixed by simple changes in Proc_test.php

Change the two lines where $command is assigned values to these.

$command = "php ".FCPATH."index.php tools proc1 $param > /dev/null &";

and

$command = "php ".FCPATH."index.php tools proc2 $param > /dev/null &";

The > /dev/null & essentially tells php to send the return to a blackhole. That means nobody has to wait for the process to finish.

Refresh the page. Yeah! No blocking!

Since we don't care that these procs return anything the lines of code in my example can be removed. So proc1() could look like this

public function proc1($param = 1)
{
    for($i = 1; $i < $param; $i++)
    {
        sqrt($i);
    }
}

So. For your particular case: In the index() method of your question replace these lines

$this->function1($empid);
$this->function2($empid);

with these

$command = "php ".FCPATH."index.php tools function1 $empid > /dev/null &";
exec($command);

$command = "php ".FCPATH."index.php tools function1 $empid > /dev/null &";
exec($command);

Obviously the functions names have to be changed in Tools.php to match what you provide to $command .

This is long enough, but if you want to see how to implement this without involving codeigniter let me know.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM