【问题标题】:How to wait for multiple WebWorkers in a loop如何在循环中等待多个 WebWorker
【发布时间】:2016-09-01 21:57:38
【问题描述】:

我对 JS 中的 Web Workers 有以下问题。我有一个重型应用程序做一些模拟。代码在多个 Web Worker 中运行。 主线程在网页上运行。但如果有意义的话,也可以是 Web Worker。

例子:

    var myWebWorkers = [];
    function openWorker(workerCount){
        for(var i = 0; i < workerCount; i++){
            myWebWorkers[i] = new Worker('worker.js');
            myWebWorkers[i].onmessage = function(e){
                this.result = e.data;
                this.isReady = true;
            }
        }
    }

    function setWorkerData(somedata){
        // somedata.length is always a multiple of myWebWorkers.length
        var elementCntPerWorker = somedata.length / myWebWorkers.length;
        myWebWorkers.forEach(function(worker, index){
            worker.isReady = false;
            worker.postMessage(
                somedata.slice(index * elementCntPerWorker, 
                    (index + 1) * elementCntPerWorker - 1));
        });
    }

    var somedata = [...];
    openWorker(8); 
    for(var i = 0; i < 10000; i++){
         setWorkerData(somedata);
         waitUntilWorkersAreDoneButAllowBrowserToReact(myWebWorkers);
         if(x % 100) updateSVGonWebPage
    }

    function waitUntilWorkersAreDoneButAllowBrowserToReact(){
        /* wait for all myWebWorkers-onchange event, but
           allow browser to react and don't block a full Web Worker 
           Following example is my intension. But will not work, because 
           events are not executed until code excution stops.
        */
        somedata = [];
        for(var i = 0; i < myWebWorkers.length; i++){
            while(!myWebWorkers[i].isReady);
            somedata = somedata.concat(myWebWorkers.result);
        }
    }

我真正需要的是waitUntilWorkersAreDoneButAllowBrowserToReact 函数或一个概念来让它运行。每次关于 Mutex、sleep 等的搜索都以以下句子结尾:“JS 是单线程的”、“这仅在您不在循环中时才有效”、“没有理由拥有睡眠功能”。等等

即使将主要任务传递给另一个 Worker,我也遇到了问题,即这个线程 100% 负责检查其他线程是否准备好,这是浪费能源和处理能力。

我希望有一个像 myWebWorker.waitForReady() 这样的阻塞函数,它允许仍然处理事件。这将使 javascript 更上一层楼。但可能我错过了一个可以做到这一点的简单概念。

谢谢!

【问题讨论】:

  • 当所有在setWorkerData(somedata) 呼叫收到消息的工作人员都向主线程响应消息时,您是否尝试呼叫waitUntilWorkersAreDoneButAllowBrowserToReact?也就是当for循环完成调用waitUntilWorkersAreDoneButAllowBrowserToReact?难以准确解释您要完成的任务?
  • 为什么在问题示例javascript 中没有message 事件处理程序?
  • @guest271314:我添加了更多代码以便于理解
  • whilefor 循环内循环冻结浏览器?网络工作者有change 事件吗?当所有网络工作者都向主线程发布消息时,您是否尝试调用函数?
  • 是的,在控制台中尝试while(true)。上面已更正为 onmessage。

标签: javascript multithreading web-worker


【解决方案1】:

我希望有一个像 myWebWorker.waitForReady() 这样的阻塞函数

不,这是不可能的。您研究的所有陈述都是正确的,网络工作者保持异步并且只会通过消息进行通信。没有等待事件,甚至在工作线程上也没有。

您需要为此使用 Promise:

function createWorkers(workerCount, src) {
    var workers = new Array(workerCount);
    for (var i = 0; i < workerCount; i++) {
        workers[i] = new Worker(src);
    }
    return workers;
}
function doWork(worker, data) {
    return new Promise(function(resolve, reject) {
        worker.onmessage = resolve;
        worker.postMessage(data);
    });
}
function doDistributedWork(workers, data) {
    // data size is always a multiple of the number of workers
    var elementsPerWorker = data.length / workers.length;
    return Promise.all(workers.map(function(worker, index) {
        var start = index * elementsPerWorker;
        return doWork(worker, data.slice(start, start+elementsPerWorker));
    }));
}

var myWebWorkers = createWorkers(8, 'worker.js');
var somedata = [...];
function step(i) {
    if (i <= 0)
        return Promise.resolve("done!");
    return doDistributedWork(myWebWorkers, somedata)
    .then(function(results) {
        if (i % 100)
            updateSVGonWebPage();
        return step(i-1)
    });
}
step(1000).then(console.log);

Promise.all 具有等待并发运行结果的魔力,step 函数使用递归方法执行 asynchronous looping

【讨论】:

    猜你喜欢
    • 2023-01-20
    • 2021-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-22
    • 2021-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多