Javascript Chrome中的主线程阻止Web Worker
我有一本书。我希望定期使用它进行网络请求。我特别想做的一件事是,即使主JS执行线程被阻塞(例如被window.alert阻塞),也要发出这些请求。我用的是Chrome38 但是,当我尝试在worker中发出网络请求时,请求似乎被UI线程阻止。下面是一个人为的例子来说明这个问题: base.js:Javascript Chrome中的主线程阻止Web Worker,javascript,multithreading,google-chrome,xmlhttprequest,web-worker,Javascript,Multithreading,Google Chrome,Xmlhttprequest,Web Worker,我有一本书。我希望定期使用它进行网络请求。我特别想做的一件事是,即使主JS执行线程被阻塞(例如被window.alert阻塞),也要发出这些请求。我用的是Chrome38 但是,当我尝试在worker中发出网络请求时,请求似乎被UI线程阻止。下面是一个人为的例子来说明这个问题: base.js: var worker = new Worker("/worker.js"); setTimeout(function() { console.log("begin blocking");
var worker = new Worker("/worker.js");
setTimeout(function() {
console.log("begin blocking");
var startDt = new Date();
var blockPeriod = 5000;
var a;
// Obviously we'd never actually do this, but this while loop
// is a convenient way to create the problem case (a blocked main
// thread).
while ((new Date() - startDt) < blockPeriod) {
a = 0;
}
console.log("stop blocking");
}, 3000);
我看到的结果是,我们看到成功的HTTP请求持续了三秒,直到阻塞开始。此时,在阻塞结束之前,我们看不到任何记录到控制台的内容,此时我们看到五个“发送请求间隔”,然后是五个响应日志,如下所示:
Send request interval
{"pong": true}
Send request interval
{"pong": true}
Send request interval
{"pong": true}
Send request interval
{"pong": true}
begin blocking
stop blocking
5x Send request interval
5x {"pong": true}
Send request interval
{"pong": true}
我在服务器日志中还看到,在阻塞时间内没有发出任何请求,然后在阻塞期结束时,这五个请求几乎同时收到
考虑到“发送请求间隔”在一行中出现了五次,工作进程显然在继续执行:如果没有,它将无法完成下一次迭代的排队。我还发现,如果我通过触发window.alert(而不是在循环中旋转)进行阻止,我会以1秒的间隔从sendRequest
的开头获取日志消息,然后在停止阻止后立即获取大量响应处理程序日志消息
在Firefox中,后台线程在这种情况下似乎完全停止了(我没有在阻塞期间得到同样的五个请求排队)。然而,在这种情况下,我只针对Chrome(我最终想要使用甚至在Firefox Workers中都不起作用的WebSocket),所以我对此并不感兴趣
所有这些加在一起,使我相信Web Workers中有一些活动类被生成线程阻止,而有些则没有(我最初在WebSocket中看到了相同的行为)。具体来说,我想知道(如果有人知道):
你的观察是正确的。当UI线程被阻止时,不会调度网络调用 更糟糕的是,Chrome拥有最好的性能。当工作线程在UI线程被阻止时发出XHR请求时:
- Chrome:所有请求都已排队。在UI线程解除阻止之前,浏览器不会实际发出请求。从好的方面来看,辅助线程仍然可以自由运行
- Firefox:
阻塞,直到UI线程解锁newXMLHttpRequest()
- IE:
阻塞,直到UI线程解除阻塞xhr.open()
没有办法解决这个问题;你需要浏览器代表你提出请求。我没有对WebSocket做过任何测试,但是即使UI线程被阻塞,它们也可能会传递事件。在最坏的情况下,收到的消息将排队等待UI线程解锁。如果有人无意中发现此行为,此行为将在2015年2月的Blink中被确认为错误(根据“错误”的松散定义为“行为不正常”):
我也遇到了同样的问题,一个Web工作者执行了一种保持活动状态的操作:它定期ping服务器,以通知页面仍然处于活动状态。我还在worker中使用console.log,但我确信这不是原因 经过一些调查后,我可以说这个问题可以解决两种不同的情况:
将控制器的会话状态标记为只读将解决此问题,而在Web.config()中完全禁用会话状态将极大地提高整个应用程序的性能。是的,在发出
警报期间它将被禁用。
:-)Bergi,感谢您的回复。然而,web workers的整个想法是,他们在后台线程中操作,不会干扰UI(bobince甚至在您链接的答案中提到了这一警告)。在某种程度上,情况显然是这样的:我上面概述的示例表明,在某种程度上,即使主线程被阻塞,它们也会被执行。我的大问题是,主线程阻塞和不阻塞之间的界限在哪里。“非阻塞不一定意味着并发”。来源文章:@sergiolius,我不确定我是否明白。那篇文章似乎声称网络工作者是一个
Send request interval
{"pong": true}
Send request interval
{"pong": true}
Send request interval
{"pong": true}
Send request interval
{"pong": true}
begin blocking
stop blocking
5x Send request interval
5x {"pong": true}
Send request interval
{"pong": true}