2 回答
![?](http://img1.sycdn.imooc.com/545868190001d52602200220-100-100.jpg)
TA贡献1786条经验 获得超11个赞
对于 Chrome(仅),您可以使用共享内存(共享缓冲区作为内存)。当您想停下来时,请在内存中举起一面旗帜。不是这个解决方案的忠实粉丝(很复杂,仅在 chrome 中受支持)。它还取决于您的查询如何工作,以及是否有冗长查询可以检查标志的地方。
相反,您可能应该多次调用 c++ 函数(例如,对于每个查询)并检查您是否应该在每次调用后停止(只需向工作人员发送一条消息即可停止)。
我所说的多次是分阶段进行查询(单个查询的多个函数校准)。它可能不适用于您的情况。
无论如何,AFAIK 无法向 Webassembly 执行(例如 Linux kill)发送信号。因此,您必须等待操作完成才能完成取消。
我附上了一个可以解释这个想法的代码片段。
worker.js:
... init webassembly
onmessage = function(q) {
// query received from main thread.
const result = ... call webassembly(q);
postMessage(result);
}
main.js:
const worker = new Worker("worker.js");
const cancel = false;
const processing = false;
worker.onmessage(function(r) {
// when worker has finished processing the query.
// r is the results of the processing.
processing = false;
if (cancel === true) {
// processing is done, but result is not required.
// instead of showing the results, update that the query was canceled.
cancel = false;
... update UI "cancled".
return;
}
... update UI "results r".
}
function onCancel() {
// Occurs when user clicks on the cancel button.
if (cancel) {
// sanity test - prevent this in UI.
throw "already cancelling";
}
cancel = true;
... update UI "canceling".
}
function onQuery(q) {
if (processing === true) {
// sanity test - prevent this in UI.
throw "already processing";
}
processing = true;
// Send the query to the worker.
// When the worker receives the message it will process the query via webassembly.
worker.postMessage(q);
}
从用户体验的角度来看一个想法:你可以创建~两个工人。这将占用两倍的内存,但允许您“立即”“取消”一次。(这只是意味着在后端,第二个工作人员将运行下一个查询,当第一个完成取消时,取消将再次立即生效)。
![?](http://img1.sycdn.imooc.com/545865da00012e6402200220-100-100.jpg)
TA贡献1843条经验 获得超7个赞
共享线程
由于工作线程和它调用的 C++ 函数共享同一个线程,工作线程也将被阻塞,直到 C++ 循环完成,并且无法处理任何传入的消息。我认为一个可靠的选项可以通过从主应用程序一次初始化一次迭代来最大程度地减少线程被阻塞的时间。
它看起来像这样。
main.js -> worker.js -> C++ function -> worker.js -> main.js
打破循环
下面,C++ 有一个初始化为 0 的变量,它将在每次循环迭代时递增并存储在内存中。然后 C++ 函数执行一次循环迭代,增加变量以跟踪循环位置,然后立即中断。
int x;
x = 0; // initialized counter at 0
std::vector<JSONObject> data
for (size_t i = x; i < data.size(); i++)
{
process_data(data[i]);
x++ // increment counter
break; // stop function until told to iterate again starting at x
}
然后你应该能够向 web worker 发布一条消息,然后它会向 main.js 发送一条消息,表明该线程不再被阻塞。
取消操作
至此,main.js 知道 web worker 线程不再被阻塞,并且可以决定是否告诉 web worker 再次执行 C++ 函数(C++ 变量跟踪内存中的循环增量)。
let continueOperation = true
// here you can set to false at any time since the thread is not blocked here
worker.expensiveThreadBlockingFunction()
// results in one iteration of the loop being iterated until message is received below
worker.onmessage = function(e) {
if (continueOperation) {
worker.expensiveThreadBlockingFunction()
// execute worker function again, ultimately continuing the increment in C++
} {
return false
// or send message to worker to reset C++ counter to prepare for next execution
}
}
继续操作
假设一切正常,并且用户没有取消操作,循环应该继续直到完成。请记住,您还应该发送有关循环是否已完成或需要继续的不同消息,这样您就不会一直阻塞工作线程。
添加回答
举报