简体   繁体   中英

How to use Web Workers for finding intersection?

I am trying to use Web Workers and it works not good. My implementation doesn't work, because it doesn't return true in any way, as I think result always false. How should I stop all workers when I found first intersection? Also all workers work very long,

This is my code

    // Delete all workers in previous iteration, because the don't need
    this.workers.forEach(function(worker, i){
        worker.terminate()
    });
    this.workers = [];
    var result = false;
    // For each line in polyline I create 4 workers for finding intersection with rectangle of selection
    for(var i=1; i<this.dots.length; ++i){
        if(result)
            return true;
        var handler = function(e){
            if(e.data.result){
                result = true;
            }
        };
        this.workers.push(new Worker("js/intersection.js"));
        this.workers[this.workers.length-1].onmessage = handler;
        this.workers[this.workers.length-1].postMessage({type: "line_vs_line", l1p1: first_dot, l1p2: {x: second_dot.x, y: first_dot.y}, l2p1: {x: this.dots[i].dot.x, y: this.dots[i].dot.y}, l2p2: {x: this.dots[i-1].dot.x, y: this.dots[i-1].dot.y}});

        this.workers.push(new Worker("js/intersection.js"));
        this.workers[this.workers.length-1].onmessage = handler;
        this.workers[this.workers.length-1].postMessage({type: "line_vs_line", l1p1: {x: second_dot.x, y: first_dot.y}, l1p2: second_dot, l2p1: {x: this.dots[i].dot.x, y: this.dots[i].dot.y}, l2p2: {x: this.dots[i-1].dot.x, y: this.dots[i-1].dot.y}});

        this.workers.push(new Worker("js/intersection.js"));
        this.workers[this.workers.length-1].onmessage = handler;
        this.workers[this.workers.length-1].postMessage({type: "line_vs_line", l1p1: second_dot, l1p2: {x: first_dot.x, y: second_dot.y}, l2p1: {x: this.dots[i].dot.x, y: this.dots[i].dot.y}, l2p2: {x: this.dots[i-1].dot.x, y: this.dots[i-1].dot.y}});

        this.workers.push(new Worker("js/intersection.js"));
        this.workers[this.workers.length-1].onmessage = handler;
        this.workers[this.workers.length-1].postMessage({type: "line_vs_line", l1p1: {x: first_dot.x, y: second_dot.y}, l1p2: first_dot, l2p1: {x: this.dots[i].dot.x, y: this.dots[i].dot.y}, l2p2: {x: this.dots[i-1].dot.x, y: this.dots[i-1].dot.y}});

    }
    return false;

That's code for workers:

onmessage = function(e){
    var l1p1 = e.data.l1p1;
    var l1p2 = e.data.l1p2;
    var l2p1 = e.data.l2p1;
    var l2p2 = e.data.l2p2;
    switch(e.data.type){
        case "line_vs_line":{
            var q = (l1p1.y - l2p1.y) * (l2p2.x - l2p1.x) - (l1p1.x - l2p1.x) * (l2p2.y - l2p1.y);
            var d = (l1p2.x - l1p1.x) * (l2p2.y - l2p1.y) - (l1p2.y - l1p1.y) * (l2p2.x - l2p1.x);
            if( d == 0 )
                postMessage({result: false});
            else{
                var r = q / d;
                q = (l1p1.y - l2p1.y) * (l1p2.x - l1p1.x) - (l1p1.x - l2p1.x) * (l1p2.y - l1p1.y);
                var s = q / d;
                postMessage({result: !( r < 0 || r > 1 || s < 0 || s > 1 )});
                console.log(r,s);
            }
            break;
        }
    }
};

Here when you make your function call, you go through, create all your workers, and then return false at the end. No matter what your function will always return false.

You seem to be misunderstanding the Async workflow of Javacript.

var handler = function(e){
        if(e.data.result){
            result = true;
        }
    }  

That function above doesn't get executed until after the main function has already returned false. This is passed as the onmessage event, but it's not synchronous so you can't modify the 'result' and return that.

A better way is to have a separate function that you call out once one of the workers completes that does the action you want to do once something is complete, OR pass in a callback function to run once one of the workers completes.

Your function currently works like this:

  1. Kill any workers working

     this.workers.forEach(function(worker, i){ worker.terminate() }); this.workers = []; 
  2. Set Result to False

     var result = false; 
  3. For each dot: check Result (always false at this point) spin up 4 workers, and pass in a callback function that when one of them completes, you set result to true.

     for(var i=1; i<this.dots.length; ++i){ if(result) return true; // This will never happen as result is false for all loops at this point. var handler = function(e){ if(e.data.result){ result = true; } }; //Etc, spin up 4 workers ... 
  4. Return false (function exits)

     return false; // This always returns false, // nothing is stopping the function from getting here. 
  5. Your workers complete 1 by one and execute that function from before, but there's no result variable to set (so it's probably setting a global variable to true)

     // Workers now execute this snippet one by one... // but on the global scope, so result is going to be set globally, // and not in your function. if(e.data.result){ result = true; } 
  6. You can't do anything with it because no other function is executing at this time.

Does that make sense? You can't think about Async workflows in the same manner as Synchronous Workflows.

Here's an article on Async: http://recurial.com/programming/understanding-callback-functions-in-javascript/

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