【ArcGIS Pro二次开发】(31):ArcGIS Pro中的多线程

news2024/11/25 12:28:50

ArcGIS Pro与旧的ArcGIS桌面应用程序的显著不同之处在于,它采用多线程架构,可以有效的发挥多核CPU的优势。这使得二次开发工具的性能变得更好,但也对开发工作带来了更多的难点和挑战。


一、多线程需要注意的问题

  • 一般情况下,为了确保响应式用户体验,图形用户界面(GUI)线程必须能够从用户那里获取输入,并流畅地输出。这意味着GUI线程和你主要的工作线程必须在不同的线程上异步执行,GUI线程不应执行其他工作,二者不能互相干扰。
  • 在后台线程上执行工作时,必须向用户显示逻辑一致且信息丰富的用户界面。应根据正在后台执行的操作,提供必要的对用户界面的操作指令,以及适当的反馈。如果长时间运行的后台操作在逻辑上可以取消,则应提供取消选项。
  • 如果操作之间存在冲突,不应同时执行,而应按适当的逻辑顺序执行。例如,当包含地图的工程仍在加载过程中时,就不能对地图执行操作。通过用户交互启动的大多数操作在逻辑上依赖于顺序,应串行执行。
  • 在异步执行时要注意多个线程同时对同一个变量、文件、要素的访问,或者错误的访问顺序,比如说,复制一个要素,再删除原要素,如果顺序反过来了,先删除就没办法复制了。这个问题在单线程中几乎不存在,因为顺序是一目了然的。但是线程一旦变多,逻辑复杂的情况下,难免会有错漏。

二、ArcGIS Pro内部线程模型

当然,我们在ArcGIS Pro二次开发中也不用那么深入学习。因为ArcGIS Pro SDK的基础架构已经降低了代码的复杂性。

在大多数情况下,我们只需处理两个线程:【用户界面线程】和应用程序提供的单个【专用工作线程】。在内部,ArcGIS Pro使用大量线程来实现栅格化、图形渲染、数据加载以及利用并行性来加速计算的选择地理处理算法。但是这些线程完全是内部线程,和我们外部的开发没有关系。

当我们调用公共API中的方法时,可能会拆分为多个内部方法去实现,并将片段委托给一个或多个的专用内部线程。


三、Task和Task异步模式

ArcGIS Pro SDK 中的方法分为三类:

1、可在任何线程上调用的异步方法。这种类型的方法会加1个【async】修饰词,通常是返回任务。但是如果返回的是变量,则需要异步调用。

2、仅在工作线程上调用的同步方法。

3、仅在GUI线程上调用的同步方法。这些类型的方法通常与WPF相关联。

.NET引入了最重要的【async】和【await】语言功能。

【async】修饰符用于标记该方法,以便编译器知道该方法是异步的。

【await】则用于异步调用方法,然后强制调用线程自动返回到下一行并在异步操作完成后继续执行。

  private async void Button_Click(object sender, RoutedEventArgs e)
  {
    double computedValue = await Task.Run<double>(()=>
    {
      double result = 42.0;        
      return result;
    });
    // 在上面await后的内容执行完毕后,才会执行下面的MessageBox任务
    MessageBox.Show(String.Format("Result was {0}",  computedValue.ToString()));
  }

以上面的代码为例,await后的异步方法执行完后,才会继续MessageBox.Show()方法。

输出结果为【Result was 42】


四、QueuedTask的使用

虽然Task可以在任意的Add-in代码中运行,但ArcGIS Pro SDK框架提供了一个更优秀的QueuedTask,实际上在开发中,我们基本就只使用到这个QueuedTask。

这是一个自定义的任务调度程序,通过使用【QueuedTask.Run】用来调度ArcGIS Pro SDK中的同步方法的任务。这种调度本质是一个排队方法,可以让多个任务有序执行。

示例代码如下:

  Task t = QueuedTask.Run(()=>
  {
    // 在此处调用同步SDK方法
  });

相较于Task类,在ArcGIS Pro SDK中使用QueuedTask类有很多优势。

1、在任务主体中,开发人员可以访问ArcGIS Pro的各种对象,例如地图、图层、要素等。这些对象的访问是线程安全的,因为QueuedTask会自动管理与主线程之间的通信。

2、如果任务需要更新UI元素,例如修改地图视图或显示进度信息,开发人员可以使用QueuedTask的Dispatcher属性,将更新操作包装在Dispatcher.BeginInvoke方法中。这样可以确保更新操作在主线程上执行,避免线程冲突。

3、如果需要取消任务,开发人员可以调用QueuedTask.Cancel方法,该方法将触发任务的取消操作。被取消的任务会在取消后尽快退出,并且可以在任务主体中进行必要的清理工作。

4、如果任务执行过程中发生异常,QueuedTask会捕获异常并将其传递给开发人员,以便进行适当的处理。开发人员可以在任务主体中使用try-catch块来捕获并处理异常。

总之,ArcGIS Pro SDK中的QueuedTask提供了一种方便而强大的机制,用于在后台执行任务并安全地与ArcGIS Pro应用程序的UI线程进行交互。它的优点包括多线程支持、UI线程安全、可取消和异常处理等。通过合理地使用QueuedTask,开发人员可以实现高效、可靠的自定义功能和扩展。

QueuedTask任务的执行顺序

这里举2个例子来说明一下QueuedTask任务的执行顺序。

            MessageBox.Show("1");
            await QueuedTask.Run(() =>
            {
                MessageBox.Show("2");
                MessageBox.Show("3");
            });
            MessageBox.Show("4");

以上面的代码为例,这是一个正常的、合理的异步执行。MessageBox的显示顺序为【1、2、3、4】。

但是如果将await的内容写成方法,并同步调用,情况则不同:

        MessageBox.Show("1");
        Spa();
        MessageBox.Show("4");

        public static async void Spa()
        {
            await QueuedTask.Run(() =>
            {
                MessageBox.Show("spa_1");
                MessageBox.Show("spa_2");
            });
        }

执行上面的代码,MessageBox的显示顺序为【1、(spa_1、spa_2)、4】。变成了并行执行,很明显,这种执行方式顺序混乱,很容易造成错误。

不幸的是,至目前为止,我已经犯了很多这样的错。

因为个人习惯将一些通用的流程写成方法并调用,造成写了很多异步的方法,在调用的时候又直接同步调用。出了不少的BUG,调来调去才发现是异步并行的原因。

在上面代码的基础上进行修改,主代码中将自定义的方法改为异步执行,方法内部改为同步执行:

        MessageBox.Show("1");
        await QueuedTask.Run(() =>
        {
            Spa();
        });
        
        MessageBox.Show("4");

        public static async void Spa()
        {
            MessageBox.Show("spa_1");
            MessageBox.Show("spa_2");
        }

运行结果,流程变回了串行执行,勉强解决了并行的问题。

基础太弱果然还是不行,这也是现在回头补基础,并记录这篇文章的主要原因。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/564593.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

尚硅谷MyBatis-Plus笔记001【简介、入门案例、基本CRUD】

视频地址&#xff1a;【尚硅谷】MyBatisPlus教程&#xff08;一套玩转mybatis-plus&#xff09;_哔哩哔哩_bilibili 尚硅谷MyBatis-Plus笔记01【简介、入门案例、基本CRUD】 尚硅谷MyBatis-Plus笔记02【】 尚硅谷MyBatis-Plus笔记03【】 尚硅谷MyBatis-Plus笔记04【】 尚硅谷…

非暴力沟通--日常沟通的技巧与实践

这篇文章是我在公司团队内部做的分享的演讲稿 开场白 大家好&#xff0c;我今天要分享的主题是非暴力沟通–日常沟通的技巧与实践。 介绍非暴力沟通这本书 分享这个主题的原因是我最近看了一本书&#xff0c;叫做《非暴力沟通》&#xff0c;这本书是美国一个叫做马歇尔卢森堡…

MFC CListCtrl 显示图片

MFC CListCtrl 显示图片 MFC CListCtrl 显示图片PreCreateWindow中设置风格没有起作用在OnCreate中设置CListCtrl的风格最合适在OnInitialUpdate中添加数据最合适需要设置CImageList&#xff0c;资源是我自己搞的一个图片资源ps:参考链接 MFC CListCtrl 显示图片 在使用MFC的C…

Codeforces Round 764 (Div. 3)

比赛链接 Codeforces Round 764 A. Plus One on the SubsetB. Make APC. Division by Two and PermutationD. Palindromes ColoringE. Masha-forgetful A. Plus One on the Subset Example input 3 6 3 4 2 4 1 2 3 1000 1002 998 2 12 11output 3 4 1题意&#xff1a; 你可…

怎么学习机械学习相关的技术?

学习机器学习相关技术的过程可以分为以下几个步骤&#xff1a; 掌握基本数学和统计知识&#xff1a; 机器学习建立在数学和统计学的基础上&#xff0c;了解线性代数、概率论、统计学等基本概念和方法对于理解机器学习算法至关重要。 学习编程和数据处理&#xff1a; 掌握一门…

kafka基础介绍

目录 前言&#xff1a; 一:kafka架构 1.kafka基础架构 2、kafka多副本架构 二、kafka基础概念 1、produce 2. Consumer 3、Broker ​ 4、Topic 5、Partition 6、Replicas 7、Offset 8、 AR 9、 ISR 10、OSR 11、HW 12、LEO 13、Lag 三、kafka特性 四、kafka…

总结加载Shellcode的各种方式

1.内联汇编加载 使用内联汇编只能加载32位程序的ShellCode&#xff0c;因为64位程序不支持写内联汇编 #pragma comment(linker, "/section:.data,RWE") //将data段的内存设置成可读可写可执行 #include <Windows.h>//ShellCode部分 unsigned char buf[] &qu…

FreeRTOS-任务通知详解

✅作者简介&#xff1a;嵌入式入坑者&#xff0c;与大家一起加油&#xff0c;希望文章能够帮助各位&#xff01;&#xff01;&#xff01;&#xff01; &#x1f4c3;个人主页&#xff1a;rivencode的个人主页 &#x1f525;系列专栏&#xff1a;玩转FreeRTOS &#x1f4ac;保持…

Spring Security入门

1. Spring Security 简介 Spring Security 是一个高度可定制的身份验证和访问控制框架&#xff0c;它基于 Spring 框架&#xff0c;并可与 Spring 全家桶无缝集成。该框架可以精确控制用户对应用程序的访问&#xff0c;控制用户的角色和权限等。 Spring Security 最早是由 Be…

C Primer Plus第三章编程练习答案

学完C语言之后&#xff0c;我就去阅读《C Primer Plus》这本经典的C语言书籍&#xff0c;对每一章的编程练习题都做了相关的解答&#xff0c;仅仅代表着我个人的解答思路&#xff0c;如有错误&#xff0c;请各位大佬帮忙点出&#xff01; 1.通过试验&#xff08;即编写带有此类…

第三节 HLMSEditor场景编辑器的编译

本节注意介绍下HLMSEditor场景编辑器的源码编译使用 一 安装依赖的资源 使用编译器为VS2019 X64&#xff0c;操作系统为WIN10&#xff0c;Ogre2.1&#xff0c;HLMSEditor 注意&#xff1a;为什么不用Ogre2.3?因为HLMSEditor版本为0.5.5&#xff0c;很久没有更新了&#xff0…

【Linux进阶之路】yum与vim操作

文章目录 前言一.yum——Linux的应用商店介绍基本使用① yum源②安装数据传输软件1.将Linux的文件传输到Windows平台上2.将Windows的文件传到Linux系统上 ③删除数据传输软件⑥查看安装包版本⑤练习安装与卸载小火车安装与卸载牛会说话 二.vim —— 一款优雅的编辑器①基本模式…

安卓基础巩固(一):工程结构、基本概念、常用布局、基本组件、动画

文章目录 安卓项目结构AndroidMainfest.xmlres资源目录简介 基本概念LayoutR类 Application与ActivityContextIntent数据传递可传递的数据类型intent.putExtra&#xff08;&#xff09;和使用Bundle的区别数据传递大小的限制 通过Intent 过滤器接收隐式 Intent&#xff1a; 单位…

国内免费的Chatgpt网站分享 支持Ai对话绘图

Chatgpt正式进入大众视野&#xff0c;已半年有余&#xff0c;作为一款媲美于百度、谷歌搜索的工具&#xff0c;它已经成为我们工作、生活、学习中不可缺少的左膀右臂&#xff0c;相比于搜索引擎&#xff0c;它寻找答案&#xff0c;不再需要自己在众多模糊不定的结果中寻找自己需…

【生物信息】调控基因组学 (Regulatory Genomics) 和Deep CNN

文章目录 Regulatory GenomicsBiological motivation of Deep CNNMulti-task CNN 来自Manolis Kellis教授&#xff08;MIT计算生物学主任&#xff09;的课《人工智能与机器学习》 主要内容就是调控基因组学和深度卷积网络的结合 由于这部分在我学习的课程中内容很少&#xff0c…

使用虚拟机安装ikuai软路由系统,搭建pppoe拨号服务器

搭建pppoe拨号服务器 一、搭建ikuai软路由系统1、VMware版本2、ikuai官网上下载系统镜像3、使用虚拟机安装ikuai系统4、登录ikuai管理界面 二、安装win7虚拟机验证拨号功能三、其他电脑要使用这个pppoe虚拟机进行拨号怎么办呢&#xff1f; 一、搭建ikuai软路由系统 先说一下背景…

【C++/嵌入式笔试面试八股】一、11.C内存分配/堆栈

C内存分配/堆栈 01.C内存分配❤️ #include <stdio.h>const int g_A = 10; //常量区 int g_B = 20; //数据段 static<

冲冲冲冲冲

目录 java基础 面向对象 集合 线程 异常 IO 反射 MySQL SpringMVC 1.SpringMVC常用的注解有哪些&#xff1f; 2.说说你对Spring MVC的理解 Spring 1. spring是什么&#xff1f; 2.Autowired和Resource关键字的区别&#xff1f; 3.说说你对Spring的IOC是怎么理解的…

计算机硬件系统 — 冯诺依曼体系结构运行原理解析

目录 文章目录 目录计算机系统计算机硬件系统&#xff08;冯诺依曼体系结构&#xff09;PC 主机硬件CPU&#xff08;中央处理器&#xff09;CPU 的组成部分CPU 总线控制器单元运算器单元寄存器组超线程与多核架构三级高速缓存为什么需要缓存三级缓存结构 CPU 的指令集指令集的类…

IIS6.0 put文件上传GetShell

目录 WebDAV 环境配置 漏洞复现 漏洞修复 WebDAV WebDAV &#xff08;Web-based Distributed Authoring and Versioning&#xff09; 是一种HTTP1.1的扩展协议。它扩展了HTTP 1.1&#xff0c;在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新HTTP请求方法&#xff0c…