37

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

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

然后webwork.js是 Web 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);
}

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

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

现在我应该已经转移了变量r,我如何从 Web Worker 本身访问它。我已经尝试过, event.rjust和其他方法,例如尝试为 的数组添加第二个函数参数,但没有任何效果。rself.rArrayBuffers

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

4

4 回答 4

70

sbr 给出的答案有效,但它会导致在发送给工作人员之前制作数据副本。对于大量数据,这可能会很慢。
要使用“可转让对象”,您实际上将对象的所有权转移到网络工作者或从网络工作者转移。这就像在没有复制的地方通过引用传递。它与普通的 pass-by-reference 的区别在于传输数据的一方不能再访问它。

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

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

以及您在网络工作者中访问它的方式:

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

在我自己的应用程序中,我需要将一个大型类型的 Float64Array 从 web worker 发送到主线程,而不会影响副本的性能。它需要大量的反复试验和搜索,所以我认为我应该在此处为遇到类似问题的其他人提供该示例。
这是在工作人员端工作的代码(arr 是我的 Float64Array):

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

在接收主线程上,我有:

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

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

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

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

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

theWorker.addEventListener('message', function(event) {
    var foo = event.data.foo;
    var arr = new Float64Array(event.data.bar);  // cast it to the desired type
    // ...
});
于 2013-05-27T05:24:08.543 回答
50
PostMesage(aMessage, transferList)

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

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

另一方面:

self.onmessage = function(objEvent)
{
    var strText = objEvent.data.str;
    var objTypedArray = objEvent.data.ab;
    var objTypedArrayView = objEvent.data.i8;
}
于 2013-06-01T17:50:10.420 回答
0

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

于 2013-05-12T15:46:33.057 回答
-5

这对我有用:

//在主

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

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

processMessage: function(ev){
    var buffer = ev.data.buffer,
    // other stuff . buffer is referenced correctly here. 
}
于 2013-05-22T21:40:24.370 回答