20

有什么方法可以同步等待或检查网络工作者中的新消息吗?

我有大量复杂的代码(从 emscripten 编译的 LLVM),我无法围绕回调进行重构。

我需要确保在我收到并处理来自 UI 线程的消息之前,某一行之后的代码不会执行。如果我用 while 循环阻塞,则事件循环永远不会运行,所以我无法接收消息。

4

5 回答 5

3

这是我在使用Pyodide时也遇到的问题。我想从主线程“同步”调用一个函数。

一种解决方案涉及Atomics 和SharedArrayBufferAPI。从 web worker 的角度来看,这看起来像下面这样

  1. postMessage主线程
  2. 冻结我们自己Atomics.wait
  3. 被主线程解冻
  4. 从 a 读取结果SharedArrayBuffer。我们无法以 接收结果postMessage,因为没有一种同步方式来询问“我收到消息了吗”。

当然,这需要相当多的额外代码来处理所有的序列化、数据传递等等。

这样做的一个限制是它不能在 Safari 中工作,因为 Safari 没有实现Atomics API。另一个限制是,要使用这些 API,需要设置 COOP/COEP 标头

还有一个带有同步 XHR 和 service worker的替代解决方案,但我还没有研究过这个选项。

于 2021-08-28T06:31:09.223 回答
1

Can you break the sequence as follow without refactoring?

wrk.onmessage = function(e) {
    if (e.data.step === 'initial input') {
        doInitialWork(e.data.inputs)
    } else if (e.data.step === 'ui input') {
        doTheRest(e.data.uiData)
    }
}

The onmessage event will be blocked until the initial step execution stack is complete and the critical ui bits will only launch when and if the info is available.

于 2015-02-07T15:31:15.363 回答
1

不,不幸的是。有一些关于添加一种方法来阻止来自父页面的消息的讨论,但它没有成功。我会看看我是否可以挖掘相关的邮件列表线程。

于 2013-05-15T17:41:43.290 回答
1

一个粗略的破解方法可能是使用同步 API,例如 FileSystem API,并使用临时文件作为同步机制。

在您的示例中,emscripten 代码可以对文件发出同步读取,而 UI 线程写入同一个文件,从而有效地解除阻塞工作人员。

于 2017-04-07T04:41:10.250 回答
0

我就是这样做的。想到 Web Workers 还没有收到await 消息功能,真的很可悲,这将使整个线程间通信概念更接近例如Go语言。但是不,他们没有这样做,所以必须发明一些东西来保持线程同步

  let resolver: any = undefined;
  let message: any = undefined;
  const messagePromise = new Promise((resolve) => resolver = resolve);

  worker.onmessage = async ({ data: payload }: { data: any }) => {
    message = payload;
    worker.onmessage = undefined;
    resolver?.();
  }

  await messagePromise;

现在,这是打字稿。只需删除类型即可获取 Javascript。请注意,如果在我们开始侦听消息之前已发送消息,则无法捕获该消息

于 2021-08-26T21:19:45.533 回答