为什么 COM+ 忽略公寓线程模型?

发布于 2024-07-21 16:47:09 字数 253 浏览 8 评论 0原文

我有一个 STA COM 组件,它被放入 COM+ 应用程序中。 客户端在该组件中创建该类的多个实例,并并行调用它们的方法。 该类已正确注册 - 相应类 ID 的“ThreadingModel”为“Apartment”。

我看到在组件内部并行执行同一类的同一方法的多次调用 - 在实际的组件代码中。 它们在同一个进程中但在不同的线程中执行。

发生了什么? COM+ 是否忽略了线程模型? STA 模型不应该一次只允许执行一个调用吗?

I have an STA COM component which is put into a COM+ application. The client creates several instances of the class in that component and calls their methods in parallel. The class is registered properly - the "ThreadingModel" for the corresponding class id is "Apartment".

I see several calls of the same method of the same class being executed in parallel inside the component - in actual component code. They are executed in the same process but in different threads.

What's happening? Is COM+ ignoring the threading model? Shouldn't STA model only allow one call at a time to be executed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

护你周全 2024-07-28 16:47:09

为了避免混淆,我不会在这个答案中使用术语“对象”。 相反,让我们使用“类”和“实例”。 我相信我们都了解它们之间的区别。

用“Apartment”的 ThreadingModel 标记您的 COM 类意味着它的实例将被加载到 STA 中。 创建这些实例的过程将确定它们是全部进入同一个 STA 还是进入单独的 STA。

正如您所发现的,COM+ 已将多个实例加载到单独的 STA 中。

使用 STA 可以保证单个实例永远不会被多个线程同时访问。 同一类的不同实例,如果它们被加载到不同的 STA 中,当然可以同时被不同的线程访问。

因此,STA 实际上是保护实例数据的一种方式。 不是你的班级数据。 COM 代码中的任何“共享”或“静态”数据都必须受到您的保护。

To avoid confusion, I won't use the term "object" in this answer. Instead let's use "class" and "instance". I'm confident we all understand the difference between them.

Marking your COM class with a ThreadingModel of "Apartment" means that instances of it will be loaded into an STA. The process creating those instances will determine whether they all go into the same STA, or into separate STAs.

As you've discovered, COM+ has loaded several instances into separate STAs.

The guarantee you get with an STA is that a single instance will never be accessed by multiple threads at the same time. Separate instances of the same class, if they are loaded into separate STAs, could certainly be accessed by different threads at the same time.

So the STA is really a way of protecting your instance data. Not your class data. Any "shared" or "static" data in your COM code will have to be protected by you.

倥絔 2024-07-28 16:47:09

STA 保证您的对象只能从单个特定线程访问——不需要针对共享变量的保护。

我记得对于 VB6,有一个特殊的模式(我不记得它是如何命名的):您可以允许 COM+ 生成多个 STA,每个 STA 使用一个专用对象。 然而,这些对象的变量被视为线程本地存储——因此,尽管可以从多个线程访问 COM 类的多个实例,但不会发生变量共享。 您是否有可能正在使用此功能?

STA guarantees that your object is only accessed from a single, specific thread -- no protection against shared variable is required.

I remember that for VB6, there was a special mode (I do not recall how it was named): You could allow COM+ to spawn up multiple STAs, each using a dedicated object. The variables of these objects, however, were treated as thread-local storage -- so although there are multiple instances of your COM class being accessed from multiple threads, no sharing of variables is taking place. Is it possible that you are using this feature?

一指流沙 2024-07-28 16:47:09

不,不是真的。 STA 字面意思是“单线程公寓”,这进一步意味着一个公寓中只能运行一个线程。 现在的问题是,什么是公寓。 单元是流程内的逻辑空间,其实现因框架而异。 Microsoft 将公寓实现为线程,因为 STA(在 Microsoft 的 COM 上下文中)转换为单线程线程,即可以有多个公寓/线程,但在 STA 的情况下每个公寓/线程都将是单线程。

你可以自己把这个东西推广到MTA。 根据我上面所说,MTA 是 COM 上下文中的多线程线程。

No, not really. STA literally means 'Single Threaded Apartment' which further means that only a single thread can run in an apartment. Now the question is that what is an apartment. Apartment is a logical space within a process and its implementation can vary from framework to framework. Microsoft implements apartments as Threads because of which an STA (in Microsoft's COM Context) translates into Single Threaded Thread i.e., there can be multiple apartments/threads but every apartment/thread will be single threaded in case of STA.

You can generalize this thing to MTA yourself. From what I said above, an MTA is a Multi-Threaded thread in COM Context.

天涯沦落人 2024-07-28 16:47:09

您是否已将该物体传递给另一套公寓中的物体? 如果是这样,您在执行此操作之前是否需要整理接口? 您是否碰巧聚合了免费线程编组器?

粗略地说,如果将对象的接口传递给另一个单元(线程)中的对象,则必须确保 编组接口。 如果不这样做,那么您可能会发现您的对象可以从另一个公寓中的对象自由调用,因为它们不是通过正确处理调用的代理进行调用。

对对象的所有调用都必须在
它的线程(在它的公寓内)。 它
禁止调用对象
直接来自另一个线程; 使用
以这种自由线程方式的对象
可能会导致应用程序出现问题。
这条规则的含义是
所有指向对象的指针都必须是
在之间传递时编组
公寓。 COM 提供以下内容
为此目的有两个函数:

* CoMarshalInterThreadInterfaceInStream 将接口编组到返回给调用者的流对象中。 
  * CoGetInterfaceAndReleaseStream 从流对象中解组接口指针并释放它。 
  

这些函数包装调用
CoMarshal接口和
CoUnmarshalInterface 函数,其中
需要使用 MSHCTX_INPROC
标志。

Have you passed the object to objects that live in another apartment? If so, did you need to marshal the interface before you did it? Did you happen to aggregate the free threaded marshaller?

Roughly speaking, if you pass an interface to your object to an object in another apartment (thread), then you must make sure to marshal the interface. If you do not, then you may find that your object can be called freely from the objects in the other apartment, since they are not calling through a proxy which handles the call correctly.

All calls to an object must be made on
its thread (within its apartment). It
is forbidden to call an object
directly from another thread; using
objects in this free-threaded manner
could cause problems for applications.
The implication of this rule is that
all pointers to objects must be
marshaled when passed between
apartments. COM provides the following
two functions for this purpose:

* CoMarshalInterThreadInterfaceInStream marshals an interface into a stream object that is returned to the caller.
* CoGetInterfaceAndReleaseStream unmarshals an interface pointer from a stream object and releases it.

These functions wrap calls to
CoMarshalInterface and
CoUnmarshalInterface functions, which
require the use of the MSHCTX_INPROC
flag.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文