2013-04-17 26 views
22

Tôi hiện đang có mã này để tạo ra một Worker Web:Sử dụng đối tượng chuyển nhượng từ một Worker Web

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

Và sau đó mã webwork.js cho Worker Web:

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); 
} 

Bây giờ tôi muốn chuyển 128-Megabyte ArrayBuffer với mã này:

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

Bây giờ tôi được cho là đã chuyển biến số r, làm cách nào để truy cập biến đó từ chính Công nhân Web. Tôi đã thử event.r, chỉ r, self.r và những thứ khác như cố gắng thêm đối số chức năng thứ hai cho mảng ArrayBuffers, nhưng không có gì hoạt động.

Tôi làm cách nào để truy cập (các) biến được chuyển từ Công nhân Web?

+0

Sẽ không nó có trong ' event.data'? – bfavaretto

+0

Không có vẻ như vậy. Nếu tôi sử dụng "w.postMessage (0, [r]);", thì "event.data" là 0, nhưng tôi không biết mảng ArrayBuffers nằm ở đâu, thậm chí bằng cách kiểm tra tất cả các thuộc tính của sự kiện. Tôi không thể tìm thấy nó. –

Trả lời

26
PostMesage(aMessage, transferList) 

trong transferList bạn phải xác định đối tượng được chuyển nhượng, trong đó chứa đựng trong aMessage:

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

Về phía khác:

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

Có ai biết nếu điều này chuyển quyền sở hữu hoặc tạo bản sao? Tôi đã thử nó và có vẻ như nó chuyển quyền sở hữu. – user1311069

+0

Tạo ArrayBuffer và Int8Array chỉ một lần! Sau đó tiếp tục gửi nó qua lại. Nếu không, sử dụng các đối tượng chuyển nhượng sẽ không có ý nghĩa gì cả. – Pawel

+0

@Pawel bạn có thể giải thích cách bạn có thể tiếp tục gửi qua lại không? Một khi bạn đã nhận được mảng, nếu bạn cố gắng postMessage nó một lần nữa trình duyệt phàn nàn với "ArrayBuffer tại chỉ số 0 đã được neutered." – RedShift

0

Hãy thử w.postMessage ([0, r]). Để sử dụng các đối tượng có thể chuyển giao, người ta cần phải vượt qua bộ đệm mảng làm mục thứ hai trên một mảng. Xem this

-2

làm việc này cho tôi:

// trong chính

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

// Trong các sợi nhân, trong xử lý tin nhắn,

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

Điều này sẽ chỉ * sao chép * ArrayBuffer; không chuyển quyền sở hữu giữa các chuỗi. – hanenbro

32

Câu trả lời được đưa ra bởi SBR hoạt động, nhưng nó sẽ gây ra một bản sao của dữ liệu được thực hiện trước khi được gửi đến người lao động. Điều đó có thể chậm cho một lượng lớn dữ liệu.
Để sử dụng "đối tượng có thể chuyển", bạn thực sự chuyển quyền sở hữu đối tượng đến hoặc từ nhân viên web. Nó giống như đi qua tham chiếu, nơi một bản sao không được thực hiện. Sự khác biệt giữa nó và tham chiếu truyền qua tham chiếu thông thường là bên chuyển dữ liệu không thể truy cập được nữa.

Tôi tin rằng con đường phải gửi dữ liệu trong ví dụ của bạn là:

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

Và cách bạn sẽ truy cập vào nó trong người lao động web:

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

Trong ứng dụng của riêng tôi Tôi cần phải gửi một Float64Array được đánh máy lớn từ nhân viên web đến chủ đề chính, mà không có hình phạt về hiệu suất của bản sao. Phải mất rất nhiều thử nghiệm và lỗi và tìm kiếm, vì vậy tôi figured tôi nên bao gồm ví dụ ở đây cho bất cứ ai khác bị mắc kẹt với một vấn đề tương tự.
Đây là mã mà làm việc ở phía người lao động (arr là Float64Array của tôi):

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

Trên chủ đề chính nhận tôi có:

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

Lưu ý rằng điều này làm việc trong Chrome, nhưng có lẽ không hầu hết các trình duyệt khác kể từ ngày này (chưa thử.)

Ngoài ra, nếu bạn muốn gửi các thông tin khác ngoài các mảng lớn, bạn có thể làm điều này:

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

Trên nhận (trong ví dụ này chính) chủ đề:

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

Câu trả lời này tốt hơn câu trả lời được chấp nhận vì nó giải thích mục đích của tham số mảng thứ hai tốt hơn nhiều. – moron4hire

0

nếu bạn muốn sử dụng người lao động web một cách dễ dàng, bạn có thể thử lib nhỏ này: WW

hy vọng nó sẽ giúp