繁体   English   中英

网络工作者突然终止

[英]Web workers terminating abruptly

我在chrome上发起了一个web worker,它有一个简单的函数,使用setTimeout重复调用。 令人惊讶的是,在调用函数大约1000次之后,Web worker终止了。 有谁能解释为什么? 我猜chrome正在做一些优化。

webworker.js

function hi() {
    postMessage('1');
    setTimeout(hi, 1);
}
hi();

main.js

var blob = new Blob([code]);
var blobURL = window.URL.createObjectURL(blob);
var worker = new Worker(blobURL);
worker.onmessage = function(data) {
    console.log(data.data); // gets called around 1000 times and done
};

编辑:转载在一个小提琴: http//jsfiddle.net/meovfpv3/1/似乎需要任意长的onmessage回调停止射击,快几秒钟,只要+5分钟

这是我对正在发生的事情的最好猜测。 通过每1ms从Web Worker发布一条消息,您要求主线程在1ms内处理每个发布的消息。

如果主线程无法在1ms内处理消息,即使未处理完最后一条消息,您仍然会向其发送新消息。 我想这会将它放入等待处理的消息队列中。

现在,由于您从Web工作者发送的消息比处理它们的速度更快,因此未处理消息的队列将变得越来越大。 在某些时候,Chrome会举手说“队列中有太多消息”,而不是排队新消息进行处理,它会丢弃它们。

这就是为什么如果你在超时中使用一个合理的数字,如100ms,消息有足够的时间在下一个消息发送之前被处理,并且没有出现未处理的消息问题。


我创建了一个jsFiddle,其中worker向主线程发送消息,主线程将消息发送回worker。 如果在发送下一条消息之前未发生该过程,则两个线程中的计数器将不匹配,并且Web worker将终止。

http://jsfiddle.net/meovfpv3/3/

您可以看到,使用100ms的合理setTimeout,所有消息都有足够的时间在下一条消息发生之前进行处理。

将setTimeout降低到1ms时,消息链没有时间在发送下一条消息之前完成,并且每个线程中的计数器最终都会被删除,使if子句跳闸并终止Web worker。


解决此问题的一种方法是,不是每隔1ms盲目地发布一条消息,而不管最后一条消息是否已被处理,只有在从主线程收到消息后才发布新消息。 这意味着您只是在主线程可以处理它们时发布消息。


为了完整性,这里是JSFiddle代码的副本:

工人:

  var counter2 = 0;
  var rcvd = true;
  function hi() {
    counter2++;
    console.log("")
    console.log("postMessage", counter2)
    postMessage(counter2);
    if (!rcvd) {
        self.close();
      console.log("No message received");
    }
    rcvd = false;
    setTimeout(hi, 1);
  }
  hi();
  onmessage = function(e) {
    rcvd = true;
    console.log("secondMessage", e.data);
  }

主要:

var ww = document.querySelector('script[type="text/ww"]'),
    code = ww.textContent,
    blob = new Blob([code], {type: 'text/javascript'}),
    blobUrl = URL.createObjectURL(blob),
    worker = new Worker(blobUrl),
    counter = 0;

worker.onmessage = function(e) {
    counter++;
  console.log("onmessage:", counter);
  worker.postMessage(e.data);
}

首先,一些观察,我无法解释,但有点有趣,可能会激发某些人的灵感:

  • @Anson - 如果我将你的jsFiddle代码放入Codepen (仍在Chrome中),那里就没有问题了。 onmessage回调只是继续工作!

  • 然后回到jsFiddle ......它甚至无法将setTimeout更改为像10s这样的长间隙,因此它不是工作人员发布消息的次数,而是在onmessage回调停止触发之前多久 - 这有很多差异。

然后我找到了一些方法来保持onmessage处理程序在这个特定的例子中保持活着:

  • 在html中添加一个按钮/链接和一个处理程序(我使用jQuery),它将在点击时终止工作程序。 只需添加此代码即可修复它。 $("#stop").on("click",function(e){e.preventDefault();worker.terminate();});
  • 只需在定义onmessage后添加console.log(worker)
  • 受到相关问题中发布的答案的启发,您还window.worker = worker在定义onmessage后添加window.worker = worker

在所有情况下再次提及worker事情似乎让它保持活力。

你是否每隔1ms尝试一次消息? 那么你可能想要使用setInterval()

setInterval(function(){
    postMessage('1');
}, 1);

编辑:我错误地看到了不存在的递归,只是因为我在寻找它。 我仍然会使用setInterval不是setTimeout

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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