• arcgis Engine C++ 多线程 问题【STA MTA COM多线程模型】


    ArcGIS Engine 10 for crossplatform C++ 程序 使用了多线程,在一个线程中使用 AO 的东西 都没问题。

    但是 如果在一个线程使用了AO 的license 初始化,在另外一个线程(在 license代码之后开启的线程)直接使用 AO的东西,这样,直接报错,com错误。

    于是我搜索了下:arcgis Engine C++ 多线程 ,虽然 不报什么希望,因为 ArcEngine 的资料 少之又少。

    结果看到了下面的文章,两个文章内容一样,前面是转载,但是我先看到的。

    http://blog.sina.com.cn/s/blog_5f08173901010brv.html

    http://anshien.blog.163.com/blog/static/169966308201082441114173/

    其中:

    2、ArcObjects线程模型
    所有的ArcObjects组件都被标记为单线程单元STA参考VS帮助文档)。每个STA都限制在一个线程中,但是COM并不限制每个进程中STA的数目。当一个方法调用进入一个STA,它被转移到STA的唯一线程。因此,在STA中的一个对象将一次只接收和处理一个方法调用,它接收的每个方法调用会到达同一线程。
    
    ArcObjects组件是线程安全的,开发者可把他们在多线程环境下使用。对于AO应用程序在多线程环境下有效运行,由AO所使用的线程单元模型,即独立线程,必须加以考虑。该模型的工作原理是消除跨线程通信。一个线程内所有ArcObjects对象的引用应当只与在同一个线程的对象进行通信。
    
    对于此模型的运行,在ArcGIS 9.X中单个对象都被设计为线程唯一,而非进程唯一。在进程中管理多个对象的资源消耗超过由制止跨线程通信所获得的性能提升幅度。
    
    对于扩展ArcGIS系统的开发者,所有对象甚至包括你创造的对象都必须遵循这一规则,孤立线程工作。如果你创建的对象做为开发的一部分,你必须确保它们是线程唯一,而不是进程唯一。线程唯一就是防止跨线程通信,这里ArcGIS Engine中多线程的首要规则。

    这意思 就是 所有AO的东西 应该放到一个线程 干活,不能跨线程 使用AO 的com组件。

    好吧,我无语了,这问题 无解了。。真是不明白,为什么要限制 在一个线程内。

    正如 后一篇文章 留言:

    写的很好,前不久用AE开发遇到了多线程的问题,一直没有解决。最后放弃了,返回到单线程的开发。   COM对象和多线程一起使用还是很麻烦的,看了您的文章,很有收获。

    AE 和 多线程 ,就是 麻烦。最终 还是 COM 对象 的错。

    不知道 我是否 理解错了。。

    ----------------

    这个  要AE 在多线程 可以使用,互补打扰,也可以,那就是 对线程 进行 下小小的修改 ,设置线程的属性 为 STA

    两种线程模型:STA和MTA。

    STA(single threaded apartments)。apartment只是一个逻辑上的概念,它可以包含一个或多个线程。一个AppDomain可以包括一个或多个apartment。STA是指该apartment中只能包含一个thread。
    MTA(multi threaded apartments)。指该apartment中可以包含多个thread。
    STA and MTA 之间最大的区别就是MTA 可以在同一个apartment 中使用所有的共享资源并发执行多个线程。 而多个STA虽然可以共享数据,但是不能并发执行线程,存在性能问题。

    具体 搜索:STA MTA 即可。

    Single-Threaded Apartments
    
    
    A process has one single-threaded apartment (STA) for each thread that called CoInitialize. Each of these apartments, in turn, may have zero or more COM objects associated with them. As the name implies, however, only one specific thread (the thread that created the apartment by calling CoInitialize) may directly access the objects within the apartment. Once associated with an apartment, a thread cannot be associated with another apartment or change the concurrency model of its apartment.
    
    To create an STA, a thread simply calls CoInitialize or CoInitializeEx(NULL, COINIT_APARTMENTTHREADED), thereby associating the calling thread with the apartment until it calls CoUninitialize. Successive calls to either of these functions by the same thread do not create additional apartments or enable you to change the concurrency model of the apartment.
    
    
    
    
    Multi-Threaded Apartments
    
    Although multi-threaded apartments, sometimes called free-threaded apartments, are a much simpler model, they are more difficult to develop for because the developer must implement the thread synchronization for the objects, a decidedly nontrivial task. On the positive side, removing an STA's synchronization mechanism gives the developer much finer control over the use of thread synchronization. They can apply it where it is actually needed rather than taking the very conservative approach of STAs, which synchronize access to the entire apartment.
    
    The first thread in a process to call CoInitializeEx(NULL, COINIT_MULTITHREADED) creates a multi-threaded apartment that will be shared with any other threads that repeat this call. Once a thread is associated with the MTA, it can directly access any object created therein, which introduces some subtle variations from the way STAs operate. In STAs, a specific thread, permanently associated with the apartment, creates an object and only this thread can ever access the object (as discussed in the preceding section). In an MTA, however, many threads may create objects in the apartment and no thread controls access. As a result, it is possible to have several threads simultaneously access an object and change class data; hence the need for synchronization objects to protect class data.
    
    It should come as no surprise that, as with STAs, global data is not thread-safe in an MTA and always needs to be adequately protected. Remember to take advantage of the inherently thread-local nature of local and automatic variables: they're allocated on the thread's stack and consequently do not need to be protected.
    
    In-process components written for MTA use the ThreadingModel registry value (ThreadingModel = Free) to indicate to clients that they should be created in the MTA. An in-process component marked as such will be created in the MTA, regardless of the apartment type of the client. If necessary, COM will create the MTA before creating the component.
    
     
    
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)
    CoUninitialize()
    
    CoInitializeEx(NULL, COINIT_MULTITHREADED)
    
    摘自:
    Understanding and Using COM Threading Models
    http://msdn.microsoft.com/en-us/library/ms809971.aspx
    http://msdn.microsoft.com/zh-cn/library/ms809971.aspx
    http://social.msdn.microsoft.com/search/en-US?query=STA
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms680112(v=vs.85).aspx

    主要就是在 线程 中 加入 CoInitlizeEx 函数,指定 设置 STA属性 就行。

     

  • 相关阅读:
    VS 2017 没有工具栏中没有Report Viewer的解决方案
    数据类型和C#关系对应
    .NET CORE部署各种问题
    .NET CORE AutoMapper使用
    .NET CORE 配置Swagger文档
    window快捷登陆linux的的设置方式(设置ssh的config配置)
    linux安装mongodb并启动
    windows更改DNS设置
    scp的使用
    浏览器缓存机制
  • 原文地址:https://www.cnblogs.com/ayanmw/p/2638335.html
Copyright © 2020-2023  润新知