Cesium之Web Workers

这篇具有很好参考价值的文章主要介绍了Cesium之Web Workers。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 引言

多线程是编程中常用的方法,例如,在桌面程序中,主线程一般是UI线程,负责UI绘制与用户交互,而运算处理往往是交给背后的工作线程,这样可以有效避免交互时的卡顿感

浏览器是多进程的,每打开一个网页,都会开启一个渲染进程,渲染进程包含:

  • GUI渲染线程 (有且只有一个)
  • JS引擎线程 (有且只有一个)
  • 事件触发线程
  • 定时器触发线程
  • 异步http请求线程

其中,JS引擎线程就是解析JS代码的线程,由于JS引擎线程有且只有一个,所以JS代码执行是单线程的(笔者注:异步函数是使用任务队列实现的,除非调用了其他线程的函数,如定时器等,不然异步函数还是单线程执行的)

GUI渲染线程与JS引擎线程是互斥的,且JS引擎线程会先执行,如果JS代码卡住会导致GUI绘制卡住

有关浏览器架构与原理,可以参考:

  • 浏览器的进程与线程--深入同步、异步问题 - 知乎 (zhihu.com)
  • Web Worker 之全面讲解 - 知乎 (zhihu.com)

Web Workers就是创建JS代码执行的线程,使得JS代码执行能以多线程的方式执行,避免JS引擎线程卡住

有关Web Workers的解释可以参考:

  • Web Workers API - Web API 接口参考 | MDN (mozilla.org)
  • Web Worker 使用教程 - 阮一峰的网络日志 (ruanyifeng.com)

本文描述浏览器中的Web Workers并基于Cesium源码进行举例

2. Web Workers

通常而言,Web Workers包含:

  • 专用线程(Dedicated Workers)
  • 共享线程(Shared Workers)
  • 后台线程(Service Workers)等

这里主要是记述通常使用的专用线程(Dedicated Workers)

Web Worker的大致的使用方法如下:

(在主线程里)创建一个Web Worker

const worker = new Worker('WebWorkerTest.js')
  • WebWorkerTest.js是Web Worker执行的JS代码文件
  • 加载Web Worker执行的JS代码文件需要使用HTTP或HTTPS协议,即,需要搭建网络服务器

(在主线程里)向创建的Web Worker发送数据

worker.postMessage([2, 3])

(在子线程Web Worker,即WebWorkerTest.js中)接收主线程的数据、处理并发送给主线程

onmessage = function(e) {
    console.log('Message received from main script')
    const workerResult = e.data[0] * e.data[1]
    console.log('Posting message back to main script')
    postMessage(workerResult)
}

(在主线程里)接收Web Worker发送的数据

worker.onmessage = (e) => {
      console.log("Result:", e.data)
    }

综上,此处创建了两个文件:WebWorkerTest.jsWebWorkerTest.html

WebWorkerTest.html代码如下:

<body>
  <script>
    const worker = new Worker('WebWorkerTest.js')
    worker.postMessage([2, 3])
    worker.onmessage = (e) => {
      console.log("Result:", e.data)
    }
  </script>
</body>

WebWorkerTest.js代码如下:

onmessage = function(e) {
    console.log('Message received from main script')
    const workerResult = e.data[0] * e.data[1]
    console.log('Posting message back to main script')
    postMessage(workerResult)
}

运行结果如下(使用VS Code和Live Server插件):

更详细的Web Worker的使用方法,可以参考以下文档:

  • Web Workers API - Web API 接口参考 | MDN (mozilla.org)
  • Web Worker 使用教程 - 阮一峰的网络日志 (ruanyifeng.com)

3. Cesium中的Web Workers

Cesium源码中,对Web Workers进行了封装,封装为TaskProcessor

源码中给出的TaskProcessor使用示例为:

const taskProcessor = new Cesium.TaskProcessor('myWorkerPath');
const promise = taskProcessor.scheduleTask({
    someParameter : true,
    another : 'hello'
});
if (!Cesium.defined(promise)) {
    // too many active tasks - try again later
} else {
    promise.then(function(result) {
        // use the result of the task
    });
}

查看源码,可以知道taskProcessor.scheduleTask()函数为:

TaskProcessor.prototype.scheduleTask = function (parameters, transferableObjects) {
  // ...
  this._worker = createWorker(this);
  return Promise.resolve(canTransferArrayBuffer()).then(function (
    canTransferArrayBuffer
  ) {
    processor._worker.postMessage(
      {
        id: id,
        parameters: parameters,
        canTransferArrayBuffer: canTransferArrayBuffer,
      },
      transferableObjects
    );

    return deferred.promise;
  });
};

createWorker()函数为

function createWorker(processor) {
  const worker = new Worker(getBootstrapperUrl());
  worker.postMessage = defaultValue(
    worker.webkitPostMessage,
    worker.postMessage
  );
  // ...
  return worker;
}

不难看出,Cesium中将Web Workers封装成了Promise,既有操作Promise的优雅,又有调用Web Workers带来的多线程优势

例如,在Scene\Primitive.js中,使用TaskProcessor创建Geometry

先是使用createGeometry.js的文件名创建TaskProcessor

if (!defined(createGeometryTaskProcessors)) {
    createGeometryTaskProcessors = new Array(numberOfCreationWorkers);
    for (i = 0; i < numberOfCreationWorkers; i++) {
        createGeometryTaskProcessors[i] = new TaskProcessor("createGeometry");
    }
}

然后创建promise数组:

promises.push(
    createGeometryTaskProcessors[i].scheduleTask(
        {
            subTasks: subTasks[i],
        },
        subTaskTransferableObjects
    )
);

最后使用Promise.all方法执行所有任务并等待结果返回:

Promise.all(promises)
    .then(function (results) {
    primitive._createGeometryResults = results;
    primitive._state = PrimitiveState.CREATED;
})
    .catch(function (error) {
    setReady(primitive, frameState, PrimitiveState.FAILED, error);
});

4. 参考资料

[1] Web Workers API - Web API 接口参考 | MDN (mozilla.org)

[2] Web Worker 使用教程 - 阮一峰的网络日志 (ruanyifeng.com)

[3] Cesium原理篇:4Web Workers剖析 - fu*k - 博客园 (cnblogs.com)

[4] 浏览器的进程与线程--深入同步、异步问题 - 知乎 (zhihu.com)

[5] Web Worker 之全面讲解 - 知乎 (zhihu.com)

[6] 使用 Service Worker - Web API 接口参考 | MDN (mozilla.org)文章来源地址https://www.toymoban.com/news/detail-424874.html

到了这里,关于Cesium之Web Workers的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Matlab编程中常用到各种数学符号和特殊字符,如希腊字母、上下标、箭头符号等。在此,我们介绍如何在Matlab中快速输入这些符号,并提供相应的源代码示例。

    Matlab编程中常用到各种数学符号和特殊字符,如希腊字母、上下标、箭头符号等。在此,我们介绍如何在Matlab中快速输入这些符号,并提供相应的源代码示例。 希腊字母: Matlab中快速输入希腊字母,可以使用latex风格的命令。例如: alpha 输入alpha,即可输入希腊字母α beta

    2024年02月14日
    浏览(42)
  • 【Cesium 编程第一篇】概述、环境搭建、界面介绍

    年前年后一直在面试,发现一个奇怪的现象:很多互联网公司经受住三年的疫情冲击,反而在疫情放开的那一刻撑不住了,很多大厂都在批量的裁员:美国硅谷、北京字节、迪士尼中国等等。在北京的朋友也是年后到现在一直没有找到合适的工作,当然不是他技术不行找不到

    2024年02月08日
    浏览(62)
  • Pytorch DataLoader中的num_workers (选择最合适的num_workers值)

    num_workers是Dataloader的概念,默认值是0。是告诉DataLoader实例要使用多少个子进程进行数据加载(和CPU有关,和GPU无关) 如果num_worker设为0,意味着每一轮迭代时,dataloader不再有自主加载数据到RAM这一步骤(因为没有worker了),而是在RAM中找batch,找不到时再加载相应的batch。缺点

    2024年02月02日
    浏览(68)
  • 实际并行workers数量不等于postgresql.conf中设置的max_parallel_workers_per_gather数量

    本文件的源码来自PostgreSQL 14.5,其它版本略有不同 并行workers并不能显箸提升性能。个人不建议使用并行worker进程,大多数情况下采用postgresql.conf默认配置即可。 PostgreSQL的并行workers是由compute_parallel_worker函数决定的,compute_parallel_worker是估算扫描所需的并行工作线程数,并不

    2024年02月10日
    浏览(34)
  • 多线程并发编程-线程篇

    系统中的一个程序就是一个进程,每个进程中的最基本的执行单位,执行路径就是线程,线程是轻量化的进程。 绿色线程,由用户自己进行管理的而不是系统进行管理的,我理解就是一个进程里面可以有多线程,一个线程里面有多进程(go里面叫协程) 线程是按照CPU分的时间

    2023年04月21日
    浏览(37)
  • service workers跟页面dom交互

    Service Workers 本身不能直接访问 DOM,因为它们在与主线程不同的线程中运行。然而,你可以使用 postMessage API 在 Service Workers 和页面之间进行通信。 以下是一个简单的示例,展示了如何使用 Service Workers 与页面 DOM 进行交互。 在 Service Worker 中 假设你有一个 Service Worker 文件(

    2024年02月07日
    浏览(59)
  • 手撕js中常见方法

    这段代码实现了一个自定义的fill2方法,用于在数组中指定的范围内填充指定的值。它接受三个参数:value表示要填充的值,start表示填充的起始索引,end表示填充的结束索引(不包含在内)。 在代码中,首先获取了数组的长度。然后对start和end参数进行处理,将它们转换为整

    2024年02月09日
    浏览(46)
  • Unity中常用到的基础函数

    Awake() :当前控制脚本实例被装载的时候调用,常用于初始化; start() :当前控制脚本第一次执行 Update() 前调用; Update() :每帧执行一次; FixedUpdate() :每固定帧绘制时执行一次,和 Update() 的不同之处在于 FixedUpdate() 是渲染帧执行,如果渲染效率低下的时候,FixedUpdate() 的调

    2023年04月14日
    浏览(41)
  • C++ 多线程编程和线程池

    c++ 多线程需要包含thread头文件 多线程调用函数代码如下 子线程和主线程同时执行,当子线程没执行完,主线程结束时,程序就会报错 join,主线程等待子线程执行完成后再执行,只能使用一次 detach,主程序结束,子线程会在后台执行 joinable,判断线程是否可以调用join和de

    2024年01月20日
    浏览(78)
  • 工作中常用到的一些sql脚本

    – 存储过程查询(存储过程/函数 查询) select * from pg_proc where lower(prosrc) like ‘%%’; – 复制表数据 insert into 表(字段) select 字段 from 表 where 条件; – 查询重复数据 select COUNT(0),字段名 from 表名 where state = ‘E’ GROUP BY 字段名 HAVING COUNT(0) 1; – 表所属库 ALTER TABLE

    2024年04月26日
    浏览(74)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包