- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我知道每个线程调用 COM 的要求 CoInitialize
在与 COM 系统交互之前。
.NET 公开了一些在线程上内部操作的项目,例如:
ThreadPool
线程BackgroundWorker
类(使用异步委托(delegate)(使用线程池线程))如果我要从线程与 COM 对象交互,我是否需要调用 CoInitialize
首先?
我问是因为可能有一些more magic that automagically calls it for me - 我不知道。
<小时/>Managed and Unmanaged Threading
For interoperability, the common language runtime creates and initializes an apartment when calling a COM object. A managed thread can create and enter a single-threaded apartment (STA) that contains only one thread, or a multi-threaded apartment (MTA) that contains one or more threads. When a COM apartment and a thread-generated apartment are compatible, COM allows the calling thread to make calls directly to the COM object. If the apartments are incompatible, COM creates a compatible apartment and marshals all calls through a proxy in the new apartment.
The runtime calls CoInitializeEx to initialize the COM apartment as either an MTA or an STA apartment.
更新二:
看来您不应该从 .NET 可以提供的任何类型的线程中使用 COM:
The Managed Thread Pool
There are several scenarios in which it is appropriate to create and manage your own threads instead of using thread pool threads:
You require a foreground thread.
You require a thread to have a particular priority.
You have tasks that cause the thread to block for long periods of time. The thread pool has a maximum number of threads, so a large number of blocked thread pool threads might prevent tasks from starting.
You need to place threads into a single-threaded apartment. All ThreadPool threads are in the multithreaded apartment.
You need to have a stable identity associated with the thread, or to dedicate a thread to a task.
更新三:
看起来您可以设置非托管线程的线程模型:
Managed and Unmanaged Threading in Microsoft Windows
A managed thread can be marked to indicate that it will host a single-threaded or multithreaded apartment. The GetApartmentState, SetApartmentState, and TrySetApartmentState methods of the Thread class return and assign the apartment state of a thread. If the state has not been set, GetApartmentState returns ApartmentState.Unknown.
The property can be set only when the thread is in the ThreadState.Unstarted state; it can be set only once for a thread.
If the apartment state is not set before the thread is started, the thread is initialized as a multithreaded apartment (MTA).
大量相互矛盾的信息。
这就是为什么我们将使用 Stackoverflow 上的人所说的作为真正的答案。
最佳答案
此处的信息实际上并不冲突 - 如果您是 COM 新手,则不一定非常清楚。
简短回答:
[STAThread]
Main()
的属性来请求运行时将主线程初始化为 STA,或使用 thread.SetApartmentState(ApartmentState.STA)在调用 thread.Start()
之前创建的新线程上 - 否则默认情况下它们是 MTA。无论如何,一旦线程启动并运行,线程单元模型就无法修改。更长的答案:有两种方法可以调用 CoInitialize - 您可以使用它来将线程初始化为单线程单元线程 (STA) 或多线程单元线程 (MTA)。上面的文字所说的是,默认情况下,新线程和线程池线程会自动预 CoInitialized 作为 MTA 风格。但是对于新线程,如果您在实际启动线程之前这样做,则可以使用 ApartmentState 来指定 STA 风格。无论如何,在它启动时,它总是以一种方式或另一种方式 CoInitialized。
请注意,基于 UI 的程序上的 Main() 标记有 [STAThread] 属性,以确保它是基于 STA 的;而在控制台应用程序上,缺少 [STAThread] 意味着它是作为 MTA CoInited 的。顺便说一句,此属性的原因是调用 Main() 的线程是您无法使用 ApartmentState 指定 STA 与 MTA 的线程 - 因为它已经在运行并且在 Main() 执行时,所以为时已晚使用它;因此,可以将该属性视为运行时在调用 Main() 之前设置单元状态的提示。
要注意的关键是 STA 通常与 UI 一起使用,并且需要消息循环(.Net WinForms 为您提供了消息循环); STA 代码不应该被 Sleep() 或类似的函数阻塞,否则你的 UI 也会阻塞。另一方面,MTA 是为工作人员使用而设计的 - 例如,后台任务、下载文件或在后台进行计算,并且通常不应该拥有 UI。您可以从其中任何一个使用 COM,但这可能取决于 COM 对象正在做什么或您从哪里获取它。如果它是一个 UI 组件,您可能希望从 STA 线程使用它;另一方面,如果它是用于下载或执行计算的组件,您通常会从 MTA 线程使用它。
上面的更新 1 基本上是说 .Net 运行时总是为您调用 CoInitialize - 但让您选择 STA 与 MTA,其中 MTA 是默认值。
上面的更新 2 基本上是说,由于 ThreadPool 线程是 MTA(并且您无法更改它),因此您应该只将它们用于执行后台操作,而不是将它们用于 UI 任务。
更新 3 表示,对于新线程,您可以选择 MTA 与 STA - 与更新 1 相同,只是对 API 更加明确。
整个 MTA 与 STA 的事情可能会变得相当复杂,建议阅读 this article作为起点。不过,总体情况主要是通过记住 STA = 单线程和 UI 来概括的; MTA = 多线程、后台/辅助任务。 (STA 与 MTA 也适用于对象,而不仅仅是线程,COM 在幕后做了一大堆工作,让不同类型的线程使用不同类型的对象。当它工作良好时,你不会意识到它并且可以幸福地忽略它;但是当您遇到限制或限制时,通常很难弄清楚到底发生了什么。)
关于.net - 在 .NET 中与 COM 交互之前是否需要调用 CoInitialize?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8901869/
我正在尝试在线程中使用 COM 接口(interface)。根据我所读到的内容,我必须在每个线程中调用 CoInitialize/CoUninitialize 。 虽然这工作正常: procedure
我正在编写一个控制台应用程序,该应用程序将为名为 Client.exe 的主应用程序创建防火墙异常(exception),该应用程序通过 FTP 将一些文档上传到我们的服务器。我从Delphi 7 W
我正在 Delphi XE2 中构建一个多线程 Windows 服务应用程序,它使用 ADO 数据库组件连接到 SQL Server。我用过CoInitialize(nil);在内部线程之前很多次,但
假设我的应用程序在启动时调用 CoInitialize,并在存在之前调用 CoUninitialize。 假设我的应用程序使用了一个第三方组件并执行类似的操作,这会导致某种失败吗? 当调用已经提交时,
假设我的应用程序在启动时调用 CoInitialize,并在存在之前调用 CoUninitialize。 假设我的应用程序使用了一个第三方组件并执行类似的操作,这会导致某种失败吗? 当 CoIniti
这是我的 ThorDetectorSwitch.cpp 文件构造函数的 C++ 代码: ThorDetectorSwitch::ThorDetectorSwitch() : _mcSwitch(__u
自创建以来已经有 16 年了,我仍然不知道为什么 CoInitialize 中有一个保留参数。方法。有谁知道(或能够做出明智的猜测)添加此参数的原因以及预期用途是什么? 最佳答案 这实际上不是为了将来
我使用 UniDac 组件连接到 PostgreSQL。我的查询正在单独的线程中运行。现在,当我在线程中使用 CoInitialize 时,我收到以下编译器错误: - [DCC Error] QryT
在具有ADO数据库连接的多线程环境中,我想知道CoInitialize是否已被调用。我该如何检查这个? 最佳答案 通常情况下,您不应该执行此检查,而只需调用 CoInitialize/CoUnInit
下面的代码,源自https://learn.microsoft.com/en-us/windows/desktop/shell/folder-info#determining-an-objects-p
我有一个 .NET 应用程序,它使用 COM Interop 使用 COM 组件,组件实例化自身,接口(interface)指针在 API cal 中返回到 .net 包装器,稍后在应用程序流程中进行
我在 Delphi 程序的线程内使用 TIdHttp 和 TXMLDocument。现在我想知道: 这些类是否使用 COM 对象,因此我需要在此线程中调用 CoInitialize 和 CoUnini
onecore\com\combase\objact\objact.cxx(812)\combase.dll!00007FF8BD322169: (caller: 00007FF8BD320F78)
我正在学习 Python 中的多线程。我正在查看在线示例,并尝试为远程连接到远程计算机的 WMI 模块尝试多线程。但是,当我使用pythoncom.CoInitialize()时,它给我一个错误,指出
-我的问题 我得到 CoInitialize has not been called exption. -我的项目结构 这是我的问题。我有一个用 C# 开发的 COM dll,MCLWrapper.d
为了学习多线程,我在 COM 线程 (TRemoteDataModule) 中创建了一个线程。 这是我的组件工厂: TComponentFactory.Create(ComServer, TServe
我正在开发一个 UI 应用程序,它会一路创建一个 COM 对象。 问题是,我想将这个 COM 对象完全“移动”到另一个线程上。 我要做的是: 创建我想将对象移动到的新线程(使用 CreateThrea
我有一个 XE2 DataSnap 服务器(Windows 服务),它在其方法中使用第 3 方进程外 COM 组件。作为 COM,我知道它需要在语句周围使用 CoInitializeEx 和 CoUn
我有一个使用 C++ DLL 的 C# Windows 窗体应用程序。在 DLL 中,我初始化 COM: auto hResult = CoInitialize(NULL); // Initializ
COM是否需要初始化才能使用SysAllocString、SysFreeString等BSTR处理函数? MSDN 说 You need to initialize the COM library o
我是一名优秀的程序员,十分优秀!