图片 1

中的多线程使用,万分化解方案

 
关于那类难点互连网搜寻会有众多化解方案,但宗旨的意味都距离非常小,大概难点出于启用线程时调用类似剪贴板Clipboard.SetDataObject出错,作者把自家的测试代码显示下:

转自原来的小说ArcGIS Engine
中的102线程使用

平昔都想写写AE中10二线程的利用,但直接苦于未有时间,终于在八月会假日闲了下来。呵呵,闲话不说了,进入正题!

图片 1

直白都想写写AE中二十八线程的使用,但一向烦心未有时间,终于在秋节假日闲了下去。呵呵,闲话不说了,进入正题!

 

 
化解方案:只需将thread.SetApartmentState(ApartmentState.STA);反注释就能够了。

       
咱们都询问到ArcGIS中管理大数据量时进度是1对一的慢,那时假让你的程序是单线程的,那可就令人着急坏了,不知底管理到哪些程度,不可能操作其余的功力,无奈~~若是在此时你可见想到用八线程才能,那就来尝试该怎么完毕吗。

     
大家都精通到ArcGIS中管理大数据量时进度是比一点也不慢,那时若是你的先后是单线程的,那可就令人干着急坏了,不知底处理到何等地步,不能够操作其余的职能,无奈~~若是在那时候你能够想到用多线程本事,那就来试试看该怎么着成功吗。

  出现的由来:

      
首先,你得稍微VS的二十八线程经验或上学经验,得通晓如何10二线程,代理(Delegate)是什么样,同步与异步又是怎么着,等等。那么些在VS的提携文书档案中都有详尽分解,在此间自身就不越俎代庖了。大家中间精神去精通ArcGIS中二十四线程吧。

 

*  单元是进程之中装有同等线程访问必要的靶子的逻辑容器。同一单元中的全体目的都尚可从该单元中的任何线程发出的调用。
.NET Framework
不选用单元,托管对象自个儿承担以线程安全的艺术采取具有共享能源。由于 COM
类使用单元,由此公共语言运维
库须求在 COM interop 的情景下调用 COM
对象时创立并开首化多少个单元。托管线程能够创制并跻身只同意有2个线程的单线程单
元 (STA) 或许隐含一个或八个线程的八线程单元 (MTA)。通过将线程的
ApartmentState 属性设置为 ApartmentState 枚举值之1
,能够调控所创建的单元的项目。由于给定线程只好起始化 COM
单元一遍,由此在首先次调用非托管代码之后就不能够改动单元类型。*

      
在ArcgIS中,我们分多少个部分解说八线程。

   
首先,你得有些VS的四线程经验或学习经验,得掌握什么二十四线程,代理(Delegate)是如何,同步与异步又是怎样,等等。那个在VS的相助文书档案中都有详尽分解,在此处本身就不越职代理了。大家内部精神去掌握ArcGIS中十二线程吧。

注:在互联网上找了两篇作品或者更能评释那一个主题素材。文章的大即便,由于多数COM在.NET景况下借使运用二十八线程的话,会产生引用的COM无法健康运作,
而假若不评释程序为STAThread的话,.NET就能够活动使用二十八线程来升高功用,那样就能招致不可预言的结局。

       一、曾几何时使用八线程

 

  A young ilder ~ an old beggar !

在开创二十拾贰线程应用程序是应注意两点:线程的安全性和线程的伸缩性。线程安全对于全数的靶子都以不行重大的,但是单独唯有线程安全的对象并不意味着成功开创二十多线程应用程序,大概说线程安全能够加强应用程序的性质。

      在ArcgIS中,大家分多少个部分演说二十四线程。

.NET框架允许你在应用程序中能够非常的慢的创始线程,然则,在编写ArcObjects代码的四线程必必要小心。ArcObjects最根本的结构是组件对象模型(COM)。从那一点来讲,编写ArcObjects的多线程的代码供给既领悟.NET八线程,又要打听COM八线程模型。

 

八线程并不三番五次令你的次第跑的高速,在重重情景下,它还会追加支出和复杂性,这几个最后会放慢程序的实行进度。当扩大的千头万绪是值得的,那么拾2线程才具使用。三个为主的原则是,要是贰个职责能够解释为分歧的单独任务时,那那几个职责是切合10贰线程的。

      1、曾几何时使用四线程

二、ArcObjects线程模型

 

负有的ArcObjects组件都被标识为单线程单元(STA参考VS援助文书档案)。种种STA都限制在一个线程中,不过COM并不限定每一个进程中STA的数额。当多少个措施调用进入二个STA,它被撤换到STA的唯一线程。由此,在STA中的3个目的将贰回只收到和管理叁个方法调用,它接受的各样方法调用会到达同壹线程。

在创建102线程应用程序是应小心两点:线程的安全性和线程的伸缩性。线程安全对于具有的靶子都以尤其首要的,然而偏偏唯有线程安全的对象并不代表成功创办10二线程应用程序,只怕说线程安全能够增长应用程序的性质。

ArcObjects组件是线程安全的,开辟者可把她们在十二线程意况下行使。对于AO应用程序在拾二线程情状下有效运维,由AO所使用的线程单元模型,即单独线程,必须加以思量。该模型的办事原理是祛除跨线程通讯。叁个线程内装有ArcObjects对象的引用应当只与在同二个线程的靶子开始展览通讯。

 

对此此模型的运营,在ArcGIS
玖.X中单个对象都被规划为线程唯一,而非进度唯1。在进程中管理多个目标的财富消耗超越由抑制跨线程通讯所得到的习性提上升的幅度度。

.NET框架允许你在应用程序中能够高效的创设线程,可是,在编写ArcObjects代码的八线程必供给小心。ArcObjects最根本的结构是组件对象模型(COM)。从这点来讲,编写ArcObjects的二10三十二线程的代码须求既明白.NET八线程,又要打听COM拾二线程模型。

对此扩大ArcGIS系统的开采者,全部指标竟然包蕴你创设的靶子都无法不遵守那1规则,孤立线程专门的学业。若是你成立的目的做为开垦的1有的,你不能够不确定保障它们是线程唯1,而不是进度唯一。线程唯1就是抗御跨线程通讯,这里ArcGIS
Engine中八线程的关键规则。

 

三、10二线程方案

多线程并不一连令你的主次跑的迅猛,在无数处境下,它还会追加支出和复杂,这一个最后会减速程序的试行进程。当扩展的繁杂是值得的,那么三二十四线程才干运用。一个基本的规则是,纵然2个任务能够分解为不相同的独门任务时,那那一个职分是符合四线程的。

尽管有不少完结二十八线程应用程序的格局,但以下三种方案是开荒者常常应用的方法。

 

叁.壹、后台线程施行长事务

2、ArcObjects线程模型

当需要要求长专门的学业实行专门的学问时,在后台施行长事务是优点的,并且同时让应用程序灵活的操作别的职分,并让分界面处于响应状态。这一操作的事例诸多,如:使用FeatureCursor来重新向DataTable装载数据,举办复杂的拓扑总结并写入新的FeatureClass。为了完毕这类职务,请牢记以下几点:

 

a.
依据在孤立模型中的线程,你不可能在线程之间共享ArcObjects的机件。相反,你须要怀恋的是,单个对象都在分别线程中,并在后台线程中,举例全体工厂须求开拓FeatureClass,创建新的FeatureClass,设置空间参考等等。

富有的ArcObjects组件都被标识为单线程单元(STA参考VS协理文档)。每种STA都限制在3个线程中,不过COM并不限量各个进度中STA的数据。当1个格局调用进入三个STA,它被调换来STA的唯1线程。因而,在STA中的多个对象将3遍只接到和管理2个办法调用,它接受的各种方法调用会到达同1线程。

b.传递给线程的保有音信务必是简约类型或托管类型的格局。

 

c.万一在某种情状下,你要从主线程向工作线程传递ArcObjects组件,能够将目的体系化成字符串,再将字符串传递给目的线程,然后再反系列化还原到目标。举例,你能够运用XmlSerializerClass类别化对象形成字符串,如办事区间(Workspace)连接属性(IPropertySet),再将这一字符串传递给目的线程,然后在干活线程中选拔Xml塞里alizerClass反类别化连接属性。那样,就将连接属性对象在后台再度创设出来,从而幸免了跨线程访问。

ArcObjects组件是线程安全的,开辟者可把她们在10贰线程情形下利用。对于AO应用程序在四线程情状下有效运作,由AO所使用的线程单元模型,即独立线程,必须加以思索。该模型的劳作规律是铲除跨线程通讯。2个线程内有着ArcObjects对象的引用应当只与在同1个线程的对象举办通讯。

当运转后台线程,你可见在用户分界面领悟职分的速度。

 

3.二、执行单机ArcObjects的应用程序

对此此模型的运作,在ArcGIS
玖.X中单个对象都被规划为线程唯一,而非过程唯一。在经过中管理八个对象的财富消耗超过由抑制跨线程通信所收获的性能提上升的幅度度。

正如微软开垦职员互联网(MSDN)网址上所说,“在.NET
Framework版本2.0中,如若线程的单元状态在运维前未有规定,新的线程就起先化为ApartmentState.MTA。主应用程序线程默许起初化为ApartmentState.MTA。您不能够由此设置代码的第三行Thread.ApartmentState属性再设置主应用程序线程到ApartmentState.STA。而应使用STAThreadAttribute取代。”

 

用作ArcObjects的开采人士,这意味着,假若你的应用程序不被视为三个单1线程应用程序开首化的,.NET框架将为具有的ArcObjects创设3个特有的单线程单元(STA)线程,因为他们被标识STA。那将招致对各个从应用程序调用ArcObjects的线程切换来这么些一定的线程上来。反过来,那迫使ArcObjects组件合在一齐调用,并最后以COM组件调用只怕慢了约50倍。幸运的是,那可幸免通过轻巧地方统一标准记重要职能为[STAThread]。

对于扩张ArcGIS系统的开拓者,全体目的竟是席卷你创设的目的都必须比照那1平整,孤立线程专门的学业。要是您创设的靶子做为开垦的一局地,你必须保证它们是线程唯一,而不是经过唯壹。线程唯一正是防范跨线程通讯,这里ArcGIS
Engine中二十多线程的根本规则。

三.3、使用托管线程池和BackgroundWorker的线程

 

线程池线程都以往台线程。线程池通过提供一个由系统管理的使用程序线程池使您利用线程更有功能。利用为每个任务创造三个新线程的线程池的独到之处是线程创制和销毁的开垦是可忽略的,它能够带来更加好的质量和越来越好的连串牢固。

三、十贰线程方案

不过,设计的保有ThreadPool线程是在多线程单元(MTA),因而不应有被用来运维ArcObjects,它们是单线程单元。若要化解此难题,您有二种选取。一个是兑现二个专用ArcObjects的线程,它被标识为STAThread并委派各个从MTA线程调用这几个专用ArcObjects线程。另一种缓和方案是选拔自定义的STA线程池的落到实处,如标识为STA线程的线程数组来运作
ArcObjects。

 

三.四、同步运营线程的出现实行

纵然有繁多得以完结四线程应用程序的法子,但以下两种方案是开垦者平时使用的办法。

在繁多气象下,您必须联合执行的面世运行的线程。平时,你要等待二个或多少个线程完毕他们的任务,当自然条件下获得满意,2个等候线程的非复信号恢复生机其任务,条件如:测试是给定线否程激活和周转,改造线程优先级,或给予别的部分条件。

 

在.NET中有两种方法来保管运作线程的施行。可用来增派线程处理的严重性几类如下:

三.壹、后台线程实施长事务

System.Threading.Thread;

 

System.Threading.WaitHandle;

当须求供给长专门的学业进行专门的学问时,在后台试行长事务是长项的,并且还要让应用程序灵活的操作别的职责,并让分界面处于响应状态。那1操作的事例多数,如:使用FeatureCursor来重新向DataTable装载数据,进行复杂的拓扑总结并写入新的FeatureClass。为了做到那类职务,请牢记以下几点:

System.Threading.Monitor;

 

System.Threading.AutoResetEvent and
System.Threading.ManualResetEvent。

a.依照在孤立模型中的线程,你不可能在线程之间共享ArcObjects的组件。相反,你必要思量的是,单个对象都在各自线程中,并在后台线程中,比如全部工厂急需开荒FeatureClass,创设新的FeatureClass,设置空间参考等等。

3.5、在几个线程共享三个托管类型

 

偶尔你的.NET应用程序的平底数据结构将是3个如DataTable或哈希表管理的靶子。这个.NET托管对象允许你在多少个线程共享数据拿到,如线程和主线程渲染他们。然而,您应该咨询MSDN
Web站点以表达那或多或少是还是不是是线程安全的。在众多状态下,3个对象是线程读安全,而写并不安全。有些集合实践联合方法,它提供了二个平底集结的1道包装。

b.传递给线程的持有新闻务必是简约类型或托管类型的花样。

在您的目的被四个线程访问的景色下,依照MSDN关于那种状态的对象线程安全规则,你应当获得2个独占锁。获得这么的独占锁能够做到地方所描述的一块儿方法,或采用lock语句,它通过赚取给定对象的交互排他锁标签八个第一块。它能够确定保障,假设另三个线程试图访问对象时,它会被打断,直到该目标被放出(退出锁)。

 

3.陆、从后台线程更新用户分界面

c.万1在某种情状下,你要从主线程向工作线程传递ArcObjects组件,能够将对象系列化成字符串,再将字符串传递给目的线程,然后再反连串化还原到对象。举例,你可以选拔XmlSerializerClass种类化对象产生字符串,如办事区间(Workspace)连接属性(IPropertySet),再将这一字符串传递给指标线程,然后在做事线程中利用XmlSerializerClass反连串化连接属性。那样,就将接连属性对象在后台再次创制出来,从而防止了跨线程访问。

在大多数处境下,您正在使用一个后台线程来实行长期的操作,你想向用户告知进程,状态,错误或任何与该线程执行的职务相关的音讯。那能够透过创新一个应用程序的用户分界面控件来促成。不过,在Windows中,窗体控件绑定到2个特定的线程(平日是主线程),并且不是线程安全的。因而,你无法不委派,从而结成,任何调用UI控件的线程来决定它的所属。该信托是由此调用Control.Invoke方法,该方法在线程上进行委托,该信托具备控件的功底窗口句柄。要证实调用者是还是不是必须调用Invoke方法,你能够利用性质Control.InvokeRequired。您必须确认保障该控件的句柄再尝试调用Control.Invoke或Control.InvokeRequired在此之前曾经创办。

 

3.7、从贰个线程调用ArcObjects而不是主线程

当运维后台线程,你可见在用户分界面了然职分的进程。

在很多二10四线程应用程序中,你将索要从分化线程调用AO组件。比如,你只怕有二个后台线程来获得Web服务,那反过来,应该扩张新的类型到地图显示,响应改变地图,或运营的geoprocessing(gp)的工具来实施某个品种分析。

 

二个充足普遍的事态是从二个沙漏事件管理方法调用ArcObjects。机械漏刻的Elapsed事件是在四个线程池的职责建议,那不是一个主线程。不过,它须求运用ArcObjects,那类似是亟需跨单元调用。但是,那能够制止管理ArcObjects的零部件,就象是AO组件是二个用户分界面控件和平运动用Invoke来调用委派到开创ArcObjects组件的主线程中。由此,未有跨单元调用。

3.二、施行单机ArcObjects的应用程序

ISynchronizeInvoke接口包含的格局有Invoke,BeginInvoke,和EndInvoke。本人落成这个方法或许是一个费劲的职务。相反,你应该有您平昔从System.Windows.Forms.Control承继的类仍旧您应当有一个帮手类,它继续自小编调节件。要么选取将提供三个粗略而使得的对于调用方法的化解方案。

 

 

正如微软开垦职员互连网(MSDN)网址上所说,“在.NET
Framework版本二.0中,固然线程的单元状态在开发银行前未有规定,新的线程就起来化为ApartmentState.MTA。主应用程序线程暗中同意开首化为ApartmentState.MTA。您不能够透过安装代码的第3行Thread.ApartmentState属性再设置主应用程序线程到ApartmentState.STA。而应选择STAThreadAttribute替代。”

delegate SomethingClassType SomeDelegate(IArray array);
SomeDelegate del = new SomeDelegate(AnotherFunc);//AnotherFunc与SomeDelegate同样的形式
IAsyncResult ireslt = del.BeginInvoke(array, null, null);//异步操作
ProgressbarForm form = new ProgressbarForm();//异步操作中的进度条窗体
form.Show();
System.Windows.Forms.Application.DoEvents();
while (!ireslt.IsCompleted)
{
System.Windows.Forms.Application.DoEvents();
}
SomethingClassType something= del.EndInvoke(ireslt);
form.Close();

 

 以上是商酌方面的演说及1个自家支付进度中的3个代码片段,希望这几个能够帮助您做到你的拾二线程程序。参考的资料如下:Windows
MSDN,ESRubiconI 的开垦者网站。

作为ArcObjects的开辟人士,那意味着,假若您的应用程序不被视为贰个单壹线程应用程序开首化的,.NET框架将为全部的ArcObjects成立一个异样的单线程单元(STA)线程,因为他们被标记STA。那将导致对每1个从应用程序调用ArcObjects的线程切换成那一个一定的线程上来。反过来,那迫使ArcObjects组件合在一齐调用,并最后以COM组件调用恐怕慢了约50倍。幸运的是,那可幸免通过轻易地方统一规范记重要功效为[STAThread]。

 

 

 

三.3、使用托管线程池和BackgroundWorker的线程

 

 

线程池线程都是后台线程。线程池通过提供多少个由系统管理的采取程序线程池使您利用线程更有效能。利用为各种任务创建三个新线程的线程池的优点是线程创制和销毁的支付是可忽略的,它能够推动越来越好的天性和更加好的种类稳固。

 

然而,设计的具有ThreadPool线程是在八线程单元(MTA),因而不应当被用来运营ArcObjects,它们是单线程单元。若要解决此难题,您有三种选用。3个是得以落成一个专用ArcObjects的线程,它被标志为STAThread并委派每一种从MTA线程调用这一个专用ArcObjects线程。另1种缓慢解决方案是选拔自定义的STA线程池的完结,如标识为STA线程的线程数组来运行ArcObjects。

 

三.四、同步运转线程的产出实践

 

在广大意况下,您必须同步施行的面世运维的线程。平时,你要等待3个或多少个线程实现他们的任务,当自然条件下得到满足,2个等候线程的时限信号恢复其职务,条件如:测试是给定线否程激活和平运动转,退换线程优先级,或予以任何一些准绳。

 

在.NET中有三种办法来保管运转线程的实行。可用来扶助线程处理的最首要几类如下:

 

System.Threading.Thread;

 

System.Threading.WaitHandle;

 

System.Threading.Monitor;

 

System.Threading.AutoResetEvent and System.Threading.ManualResetEvent。

 

③.5、在五个线程共享一个托管类型

 

有时候你的.NET应用程序的底层数据结构将是多个如DataTable或哈希表管理的靶子。那一个.NET托管对象允许你在八个线程共享数据获得,如线程和主线程渲染他们。但是,您应该咨询MSDN
Web站点以注明那点是不是是线程安全的。在多数情状下,3个对象是线程读安全,而写并不安全。有个别集结试行联合方法,它提供了贰个尾部集合的同步包装。

 

在你的靶子被五个线程访问的景观下,依照MSDN关于那种场合包车型客车对象线程安全规则,你应当得到三个独占锁。获得这么的独占锁可以不辱任务地点所描述的二只方法,或使用lock语句,它通过赚取给定对象的互相排他锁标签一个第一块。它能够保证,借使另3个线程试图访问对象时,它会被卡住,直到该目的被放走(退出锁)。

 

三.6、从后台线程更新用户分界面

 

在抢先1半场馆下,您正在选用三个后台线程来施行长期的操作,你想向用户告知进程,状态,错误或别的与该线程施行的职务相关的音讯。那能够经过立异1个应用程序的用户分界面控件来落到实处。不过,在Windows中,窗体控件绑定到二个特定的线程(通常是主线程),并且不是线程安全的。因而,你必须委派,从而组合,任何调用UI控件的线程来决定它的所属。该信托是透过调用Control.Invoke方法,该措施在线程上推行委托,该信托具备控件的根基窗口句柄。要表明调用者是还是不是必须调用Invoke方法,你能够行使质量Control.InvokeRequired。您必须确认保障该控件的句柄再品尝调用Control.Invoke或Control.InvokeRequired在此以前已经成立。

 

三.7、从三个线程调用ArcObjects而不是主线程

 

在大多三十二线程应用程序中,你将急需从不一致线程调用AO组件。比如,你大概有3个后台线程来赢得Web服务,那反过来,应该增添新的项目到地图显示,响应更换地图,或运营的geoprocessing(gp)的工具来实践有些项目分析。

 

二个卓殊布满的图景是从多少个放大计时器事件管理方法调用ArcObjects。放大计时器的Elapsed事件是在3个线程池的职分提出,那不是叁个主线程。不过,它供给利用ArcObjects,那看似是急需跨单元调用。可是,这能够防止管理ArcObjects的零件,就像AO组件是1个用户分界面控件和利用Invoke来调用委派到创制ArcObjects组件的主线程中。由此,未有跨单元调用。

 

ISynchronizeInvoke接口包含的方法有Invoke,BeginInvoke,和EndInvoke。自己实现那么些格局或然是3个千斤的天职。相反,你应有有你直接从System.Windows.Forms.Control承继的类依然您应该有2个帮手类,它继续自我调整件。要么选拔将提供3个简短而卓有功能的对于调用方法的缓和方案。

 

 

 

delegate SomethingClassType SomeDelegate(IArray array);

 

Func()

 

{

 

………………

 

          SomeDelegate del = new
SomeDelegate(AnotherFunc);//AnotherFunc与SomeDelegate同样的款式

 

          IAsyncResult ireslt = del.BeginInvoke(array, null,
null);//异步操作

 

 

 

          ProgressbarForm form = new
ProgressbarForm();//异步操作中的进程条窗体

 

          form.setProgressBar(“提醒”, “正在管理数据…”, 十, 0, 拾0);

 

 

 

          form.Show();

 

          System.Windows.Forms.Application.DoEvents();

 

          while (!ireslt.IsCompleted)

 

          {

 

              System.Windows.Forms.Application.DoEvents();

 

          }

 

          SomethingClassType something= del.EndInvoke(ireslt);

 

          form.Close();

 

………

 

}

 

如上是论战方面包车型大巴阐发及二个本身支付过程中的二个代码片段,希望那一个能够接济您完了你的二十多线程程序。参考的材质如下:Windows
MSDN,ES中华VI 的开荒者网址。

小说出处:http://anshien.blog.163.com/blog/static/169966308201082441114173/