问题标签 [apartments]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
367 浏览

.net - STA applies to objects and functions?

My understanding of STA is that if my thread is running in an STA apartment then I do not have to worry about thread safety and calls to the functions of my thread are automagically queued.

My question is that if I start a worker thread in STA and then obtain an object from that thread via a function, do I have to worry about thread safety when using that object? Or are function calls on that object thread-safe?

0 投票
1 回答
808 浏览

com - 从工作线程调用(编组)单元线程 COM 接口的 ATL 示例

我正在寻找一个代码示例,它说明在 ATL COM 服务器 DLL 中进行跨线程 COM 调用。认识一个?

更多细节:

我的组件是一个 IE 浏览器帮助对象,它需要在后台线程上工作。在从 IE 的主线程调用的对象方法之一中,IE 给了我一个指向 IE DOM ( IHtmlWindow2) 的指针,我将它存储在一个本地成员变量中。

现在我想创建一个工作线程,它可以异步调用我刚刚存储的 COM 接口指针上的方法。

如果重要的话,我的调用将在我从 IE 获取接口指针的方法返回后发生,因此当我尝试从我的工作线程进行调用时,IE(而不是我的代码)将拥有控制权。

我的组件和宿主应用程序都是单元线程的。

任何人都知道一个很好的 C++ 示例来展示这是如何完成的?

我特别在寻找一个简短、直接的示例(而不仅仅是指向相关文档的指针),因为我阅读了这个问题及其答案,并且对从头开始编写实现所需的学习量感到害怕。任何时候有人建议在编写代码之前阅读 Don Box 的书,你就知道你要度过一个漫长而混乱的夜晚...... :-)

0 投票
1 回答
6646 浏览

c# - 0x80010100:系统调用失败”异常,ContextSwitchDeadlock

长话短说:在使用 COM inproc-server (dll) 的 C# 应用程序中,我遇到“0x80010100:系统调用失败”异常,并且在调试模式下还有 ContextSwitchDeadlock 异常。

现在更详细:

1)C#app初始化STA,创建COM对象(注册为“Apartment”);然后 in 订阅它的连接点,并开始使用该对象。

2) 在某个阶段,COM 对象会生成很多事件,将一个非常大的 COM 对象集合作为参数传递,这些对象是在同一个单元中创建的。

3)C#端的event-handler处理上述集合,偶尔调用对象的一些方法。在某个阶段,后面的调用开始失败,并出现上述异常。

在 COM 端,公寓使用了一个隐藏窗口,其 winproc 如下所示:

事件从 COM 服务器的其他部分发布到此窗口:

这些事件是与实际参数绑定的标准 ATL CP 实现,它们归结为如下内容:

在 C# 中,处理程序如下所示:

===================

那么,上述问题是否会仅仅因为公寓的消息队列中过多地加载了它试图传递的事件而发生呢?或者应该完全阻止消息循环以导致这种行为?

让我们假设消息队列有 2 个连续事件,这些事件评估为“onEvent”调用。第一个输入 C# 托管代码,它尝试重新输入非托管代码,同一个单元。通常,这是允许的,我们经常这样做。什么时候,什么情况下会失败?

谢谢。

0 投票
1 回答
8646 浏览

activex - 无法实例化 ActiveX 控件,因为线程位于单线程单元中。将 PC 从睡眠中唤醒后发生

我正在开发一个 VOIP 客户端(窗口形式),它在拨打或接听电话时会打开一个浏览器窗口(ExtendedWebBrowser)。通常它工作正常,但如果计算机进入睡眠模式然后唤醒程序将崩溃并出现以下错误:

我尝试在代码中设置线程,thread.SetApartmentState(ApartmentState.STA)但我得到了相同的结果。另外,我确实有[STAThread]之前的main()功能。现在我想知道它是否与计算机进入睡眠状态时线程未正确终止有关,但我不确定。我的背景是 C++ 和 DirectX,这是我工作过的第一个 Windows 窗体,因此将不胜感激。

跟进:在发现程序在工作线程而不是主线程上启动后,我能够解决这个问题。可以在此处阅读更多信息:Sleep(suspend) 和 Resuming windows form 在工作线程而不是主线程上启动程序

0 投票
2 回答
145 浏览

multithreading - 公寓是在服务器端还是在客户端在进程外环境中“生活”?

我很难理解外部进程环境中的 COM 公寓。

基本上我不明白为什么客户需要打电话CoInitializeEx在公寓中注册它自己的线程。我可以理解服务器线程使用的对象以及 STA 或 MTA 中的服务器线程。但我不明白为什么客户应该关心这个。

每个文件/指南都说客户必须打电话CoInitializeEx才能在公寓中注册。这是否意味着服务器会跟踪客户端的线程?或者公寓数据也分配在客户端进程上?

0 投票
1 回答
631 浏览

com - 带有 MTA 的进程外 COM 服务器

我有一个已创建为自由线程 ( CComMultiThreadModel)的 out of proc COM (ATL) 服务器

我对这与重新进入我的对象的调用有何关系感到有些困惑,例如,我假设我将被允许同时从多个客户端调用并同时处理这些请求,但是看起来(根据我的日志)每个请求都被序列化。

我错过了什么,简单地创建一个作为 MTA 的类是否意味着它确实是或者还有其他我必须做的事情。请注意,我在这里指的是多个进程都进行并发调用,而不是单个进程中的线程,因此COINIT_MULTITHREADED不是问题。

来自一些关于 MTA 的 MS 文档的片段似乎一切都应该开箱即用:

多个客户端可以同时从不同的线程调用支持自由线程的对象。在自由线程的进程外服务器中,COM 通过 RPC 子系统在服务器进程中创建一个线程池,并且客户端调用(或多个客户端调用)可以随时由这些线程中的任何一个传递

0 投票
1 回答
178 浏览

visual-studio-2010 - 无法从 .Net wcf 服务创建用非托管代码编写的 com 组件的对象

我正在编写一个 Wcf 服务库并想加载一个非托管的 com dll。未设置 com dll 线程模型,因此它是仅在主 STA线程模型中运行的单线程遗留组件

在 wcf 服务中,我已将公寓设置为 STA

现在,当我尝试创建 com 组件的实例时,它给出了一个异常

当我调试 com dll 时,它抛出了一个错误RPC_E_WRONG_THREAD

我可以通过将线程模型设置为Free Threaded Marshaller. 但我不允许更改 com dll 的当前线程模型。

所以请帮助我如何从 wcf 服务访问 com dll?

.Net 框架 4.0,Windows 7 x64

0 投票
1 回答
957 浏览

c++ - CoRegisterClassObject 破坏了线程安全

我正在测试一个将使用 coregisterclassobject 注册的自定义类工厂,我注意到它会导致线程问题。

我创建了一个测试 com 对象并创建了它的一个实例,一切都按预期运行。它是一个 inproc 服务器,在注册表中,它的 ThreadingModel 是“Apartment”。如果我用 apartment_threaded 调用 CoInitializeEx,它会在同一个线程上创建对象,如果我用 COINIT_MULTITHREADED 调用它,它应该在一个单独的线程上创建它(因为它不能在多线程单元中创建)。

但是,如果我首先创建自定义类工厂的实例并将其注册到 coregisterclassobject,则该对象总是在同一个线程上创建,即使线程模型与线程的单元不匹配。我认为使用 coregisterclassobject 不会改变线程在多线程单元中并且对象只能在单线程单元中的事实。

以上按预期生成了新线程,但如果我取消注释注释行,COM 不会创建任何新线程。我的类工厂没有做任何奇怪的事情。它只是加载 dll directyl 并调用 DllGetClassObject 来获取 com 定义的类工厂并在其上调用 createinstance。对 HelloWorld 的调用仍然有效,但我只是不确定为什么线程不是我所期望的。

0 投票
0 回答
475 浏览

c++ - 如何在 IClassFactory::CreateInstance 中显式设置对象的单元而不是使用当前线程的单元

我正在尝试使用 CoRegisterClassObject 注册一个自定义类工厂,并且该工厂需要能够同时处理 STA 和 MTA 对象。我注意到 IClassFactory::CreateInstance 使用 CoInitializeEx 为当前线程指定的任何线程模型。有没有办法在不同的公寓中创建对象并以某种方式将其编组回当前公寓?例如,

如果 TestComObjCoClass 需要是单线程的,我希望能够在 CustomClassFactory::CreateInstance 中做一些事情,可以在 STA 中创建对象并将其编组到 MTA 中的当前线程。

0 投票
0 回答
1188 浏览

c++ - coregisterclassobject 不适用于从另一个线程编组的类工厂

我正在尝试使用 CoRegisterClassObject 来自定义加载包含 com 对象的 dll 的方式。我正在尝试解决当线程的单元类型与 com 对象不匹配时遇到的问题。我遇到了一个问题,虽然 coregisterclassobject 返回 S_OK,但似乎没有做任何事情,因为 com 对象仍然依赖于要创建的注册表。这是我写的一个示例,作为失败的概念证明(TestComObj 是单元线程)。

这是我主要功能的相关部分。

这个想法是,由于注册表不应该与 CoRegisterClassObject 一起使用,我需要在 STA 而不是当前的 MTA 线程中手动创建单元线程对象。我注意到,当不使用 CoRegisterClassObject 时,CoGetClassObject 会产生一个新线程并在该线程中调用 DllGetClassObject,所以我认为只需要在 STA 中创建类工厂,然后对象就会在那里。

我看到的问题是,在上面的代码中,它仍然使用注册表来创建 TestComObj,即使 ClassFactory 行为正常。现在很简单。它只是在正确的 dll 上调用 LoadLibrary,然后调用 dllgetclassobject,并在其结果上调用 createinstance。当不处理单元和线程问题时,我可以使用它来创建 com 对象而无需注册它。所以我不确定这里出了什么问题。