我在js中实现了类似于.net / c#:
中的Thread类的Thread类
function Thread(func) {
var o = this;
o.func = func;
}
Thread.prototype.Start = function (p, cb) {
var o = this;
var toClass = {}.toString;
var wcode = "" + o.func;
var re = /\((.*?)\)/;
var rearr = re.exec(wcode)[1].split(",");
var odta = {};
var tobj = [];
var pstr = "";
for (var i = rearr.length - 1; i >= 0; i--)
{
odta[rearr[i]] = p ? p[i] : p;
pstr += rearr[i] + "=" + rearr[0] + ".data." + rearr[i] + ";";
if (p && p[i] && (toClass.call(p[i]) == "[object ArrayBuffer]")) {
// tobj[tobj.length] = p;
// trace("added arraybuffer");
}
}
wcode = wcode.replace("{", "{" + pstr);
re = /return ([^;\}]*?)([;\}])/g;
wcode = wcode.replace(re, "postMessage($1)$2");
//trace("re:" + wcode);
var blob = new Blob(["onmessage = " + wcode ]);
// Obtain a blob URL reference to our worker 'file'.
var blobURL = window.URL.createObjectURL(blob);
var worker = new Worker(blobURL);
worker.onmessage = function (e) {
trace("callback from worker " + e.data);
if (cb)
cb(e.data);
};
worker.postMessage(odta, tobj);
};

现在我想实施“加入”#39;方法,即等待网络工作者完成(或发送表明已完成的消息)。我知道我可以使用计时器,但这不会保留打电话的上下文,关闭也不是我想要的,它可能是一个真实的'阻止电话。
它适用于Chrome& FF(我已经放弃了IE)。
有没有办法像.net的join-method那样进行这样的阻止调用?
答案 0 :(得分:0)
您可以使用Promise
构造函数Promise.all()
function handleWorker(/* args */) {
return new Promise((resolve, reject) => {
// create worker, do stuff
worker.onmessage = function(e) {
resolve(/* optionally pass a value */)
}
worker.onerror = function(err) {
reject(err)
}
})
}
var workers = [];
for (var i = 0; i < 4; i++) {
workers.push(handleWorkers(/* arg */))
}
Promise.all(workers)
.then(res => console.log("all workers have posted message", res));
// handle error
.catch(function(workerError) {
console.log(workerError)
});
jsfiddle https://jsfiddle.net/yo8r3fzw/
答案 1 :(得分:0)
由于我一直在开发支持并发编程的多线程JS API(OODK-JS),我可以直截了当地回答:
无法阻止线程等待来自另一个线程的信号。
为什么呢?
因为webworkers通过消息交换与主线程通信。一个好的尝试是在主线程中实现一个无限循环,并将一个变量设置为stop条件,当主线程收到来自webworker的消息以打破循环时,该变量将被更新。不幸的是,由于主线程是循环的,因此在循环完成之前不会收到来自webworkers的消息,因为它是主线程保持循环不确定。
解决方案?
阻止主线程是不可能的,但是当每个webworker发送消息'task.done'时,当所有webwokers完成作业时,仍然可以通过实现计数器递增来触发动作。一旦计数器达到初始化的webworkers数量,就可以触发一个动作
答案 2 :(得分:0)
我已经尝试过guest271314的建议,但还没有,希望静态Promise.resolve会阻止,因为文档说它返回一个“已解决”的承诺。这是我到目前为止所做的:
function Thread(func) {
var o = this;
o.func = func;
}
Thread.prototype.Start = function (p, cb) {
var o = this;
var toClass = {}.toString;
var wcode = "" + o.func;
trace(wcode);
var re = /\((.*?)\)/;
var rearr = re.exec(wcode)[1].split(",");
var odta = {};
var tobj = [];
var pstr = "";
for (var i = rearr.length - 1; i >= 0; i--)
{
odta[rearr[i]] = p ? p[i] : p;
pstr += rearr[i] + "=" + rearr[0] + ".data." + rearr[i] + ";";
if (p && p[i] && (toClass.call(p[i]) == "[object ArrayBuffer]")) {
tobj[tobj.length] = p[i];
// trace("added arraybuffer");
}
}
wcode = wcode.replace("{", "{" + pstr);
re = /return ([^;\}]*?)([;\}])/g;
wcode = wcode.replace(re, "postMessage($1);return;$2");
//trace("re:" + wcode);
var blob = new Blob(["onmessage = " + wcode ]);
// Obtain a blob URL reference to our worker 'file'.
var blobURL = window.URL.createObjectURL(blob);
var worker = new Worker(blobURL);
o.promise = new Promise(function(resolve, reject) {
worker.onmessage = function (e) {
trace("callback from worker " + e.data);
if (cb)
cb(e.data);
resolve();
};
});
worker.postMessage(odta, tobj);
};
Thread.prototype.Join = function () {
var o = this;
Promise.resolve(o.promise);
// I'd like to get here AFTER the worker has finished
};
用以下方法测试:
var t = new Thread(myfunction);
t.Start([1, 2, 3, new ArrayBuffer(2)]);
t.Join();
trace("Thread done!");