「メインスレッド」と SharedArrayBuffer を共有する Worker があります。正しく動作させるには、メイン スレッドが SAB にアクセスする前に、ワーカーが SAB にアクセスできることを確認する必要があります。(編集: ワーカーを作成するコードは、別の関数 (EDIT2: SAB を指す配列を返す) にある必要があります) (おそらく、これはすでに不可能です。教えてください)。
初期コードは次のようになります。
function init() {
var code = `onmessage = function(event) {
console.log('starting');
var buffer=event.data;
var arr = new Uint32Array(buffer);// I need to have this done before accessing the buffer again from the main
//some other code, manipulating the array
}`
var buffer = new SharedArrayBuffer(BUFFER_ELEMENT_SIZE);
var blob = new Blob([code], { "type": 'application/javascript' });
var url = window.URL || window.webkitURL;
var blobUrl = url.createObjectURL(blob);
var counter = new Worker(blobUrl);
counter.postMessage(buffer);
let res = new Uint32Array(buffer);
return res;
}
function test (){
let array = init();
console.log('main');
//accessing the SAB again
};
ワーカー コードは常に の後に実行されtest()
、コンソールには常に が表示されmain
、次にが表示されstarting
ます。
タイムアウトを使用しても役に立ちません。の次のコードを検討してくださいtest
。
function test (){
let array = [];
console.log('main');
setTimeout(function(){
array = initSAB();
},0);
setTimeout(function(){
console.log('main');
//accessing the SAB again
},0);
console.log('end');
};
コンソールにはend
、最初に 、続いてが表示main
されstarting
ます。
ただし、test() 関数の外でバッファをグローバル配列に割り当てると、タイムアウトがなくても機能します。
私の質問は次のとおりです。
- メッセージが送信された (= 受信された) 直後にワーカーが起動しないのはなぜですか? 私の知る限り、ワーカーには独自のイベント キューがあるため、メイン スタックが空になることに依存するべきではありませんか?
- メッセージの送信後にワーカーがいつ作業を開始するかについての詳細な仕様はありますか?
- グローバル変数を使用せずに SAB に再度アクセスする前にワーカーが開始されたことを確認する方法はありますか? (忙しい待機を使用することもできますが、注意してください...)おそらく方法はありませんが、確認したいと思います。
編集
より正確には:
- 完全に並行して実行されるシナリオでは、ワーカーは投稿された直後にメッセージを処理できます。これは明らかにそうではありません。
- ほとんどの Browser API (および Worker はそのような API) は、コールバック キューを使用して API への呼び出しを処理します。しかし、これが適用されると、タイムアウトのコールバックが実行される前に、メッセージがポスト/処理されます。
- さらに先へ: postMessage の後に SAB から読み取ってビジー状態にしようとすると、1 つの値が変更されるまでプログラムが無限にブロックされます。私の知る限り、この動作は文書化されておらず、説明できません 。
要約すると、postMessage の呼び出しが関数内にある場合、ブラウザーがメッセージを投稿するタイミングを決定し、ワーカーがそれを処理する方法を知りたいです。私はすでに回避策 (グローバル変数) を見つけたので、それが舞台裏でどのように機能するかにもっと興味があります。しかし、誰かが私に実用的な例を見せてくれるなら、私はそれを取ります.
編集2:
グローバル変数を使ったコード(うまく動くコード)はこんな感じ
function init() {
//Unchanged
}
var array = init(); //global
function test (){
console.log('main');
//accessing the SAB again
};
を出力starting
しmain
てから、コンソールに出力します。
注目に値すること: Firefox ブラウザー(Chrome はテストされていません)でコードをデバッグすると、グローバル変数( starting
before main
) なしで必要な結果が得られます。誰か説明できますか?