javascript 使用来自 Web Worker 的可传输对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16071211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 03:09:16  来源:igfitidea点击:

Using transferable objects from a Web Worker

javascriptweb-workertransferable

提问by alt.126

I currently have this code to create a Web Worker:

我目前有这个代码来创建一个 Web Worker:

w = new Worker("webwork.js");
w.onmessage = function(event) { alert(event.data); }

And then the webwork.jscode for the Web Worker:

然后是webwork.jsWeb Worker的代码:

self.onmessage = function(event) {
    //var ss=r;  //Causes error because of undefined
    var ss="";
    for(var currProp in event) {
        ss+=("event."+currProp+"="+event[currProp]+"\n");
    }
    postMessage(ss);
}

Now I want to transfer a 128-Megabyte ArrayBufferwith this code:

现在我想ArrayBuffer用以下代码传输 128 兆字节:

var r = new ArrayBuffer(1048576*128);
w.postMessage(0, [r]);


Now that I have supposedly transferred the variable r, how do I access it from the Web Worker itself. I have tried event.r, just r, self.rand other things like trying to add a second function argument for the array of ArrayBuffers, but nothing works.

现在我应该已经传输了变量r,我如何从 Web Worker 本身访问它。我已经尝试过event.r,只是rself.r以及其他一些事情,比如尝试为 的数组添加第二个函数参数ArrayBuffers,但没有任何效果。

How can I access the transferred variable(s) from the Web Worker?

如何从 Web Worker 访问传输的变量?

回答by yanni

The answer given by sbr works, but it would cause a copy of the data to be made before being sent to the worker. That could be slow for a large amount of data.
To use "transferable objects" you actually transfer the ownership of the object to or from the web worker. It's like passing by reference where a copy isn't made. The difference between it and the normal pass-by-reference is that the side that transferred the data can no longer access it.

I believe the way you should send the data in your example is:

sbr 给出的答案有效,但它会导致在发送给工作人员之前制作数据的副本。对于大量数据,这可能会很慢。
要使用“可转移对象”,您实际上是将对象的所有权转移到 Web Worker 或从 Web Worker 转移。这就像在没有复制的情况下通过引用传递。它与普通的传递引用的区别在于,传输数据的一侧无法再访问它。

我相信您应该在示例中发送数据的方式是:

w.postMessage(r,[r]);  // first arg is r, not 0 as in the question

And the way you would access it in the web worker:

以及您在 Web Worker 中访问它的方式:

addEventListener('message', function(event) {
    var r = event.data;
});


In my own application I needed to send a large typed Float64Array from the web worker to the main thread, without the performance penalty of the copy. It took lots of trial and error and searching, so I figured I should include that example here for anyone else who gets stuck with a similar problem.
This is the code that worked on the worker side (arr is my Float64Array):

在我自己的应用程序中,我需要从 web worker 向主线程发送一个大类型的 Float64Array,而不会造成副本的性能损失。进行了大量的反复试验和搜索,所以我想我应该在此处包含该示例,以供其他遇到类似问题的人使用。
这是在工作端工作的代码(arr 是我的 Float64Array):

self.postMessage(arr.buffer, [arr.buffer]);

On the receiving main thread I have:

在接收主线程上,我有:

theWorker.addEventListener('message', function(ev) {
    var arr = new Float64Array(ev.data);  // just cast it to the desired type - no copy made
    // ...
});

Note that this works in Chrome, but maybe not most other browsers as of this date (haven't tried yet.)

Also, if you want to send other information in addition to the large array, you can do this:

请注意,这在 Chrome 中有效,但截至目前可能不适用于大多数其他浏览器(尚未尝试)。

此外,如果您想发送除大数组之外的其他信息,您可以这样做:

self.postMessage({foo:"foo", bar:arr.buffer}, [arr.buffer]);

On the receiving (in this example the main) thread:

在接收(在本例中是主)线程上:

theWorker.addEventListener('message', function(event) {
    var foo = event.data.foo;
    var arr = new Float64Array(event.data.bar);  // cast it to the desired type
    // ...
});

回答by CoolCmd

PostMesage(aMessage, transferList)

In transferListyou must specify transferable objects, which contained in aMessage:

transferList您必须指定可转移对象,其中包含aMessage

var objData =
{
    str: "string",
    ab: new ArrayBuffer(100),
    i8: new Int8Array(200)
};
objWorker.postMessage(objData, [objData.ab, objData.i8.buffer]);

On other side:

另一方面:

self.onmessage = function(objEvent)
{
    var strText = objEvent.data.str;
    var objTypedArray = objEvent.data.ab;
    var objTypedArrayView = objEvent.data.i8;
}

回答by Wyatt

Try w.postMessage([0,r]). To use transferable objects, one needs to pass the array buffer as the second item on an array. See this

试试 w.postMessage([0,r])。要使用可传输对象,需要将数组缓冲区作为数组的第二项传递。看到这个

回答by sbr

this works for me :

这对我有用:

//in the Main

//在主

var x = new ArrayBuffer(1048576*128);
w.postMessage({buffer: x});

// In the worker thread, in message handler,

// 在工作线程中,在消息处理程序中,

processMessage: function(ev){
    var buffer = ev.data.buffer,
    // other stuff . buffer is referenced correctly here. 
}