你能用你自己的话解释一下STA和MTA吗?
另外,什么是公寓线程,它们只与COM有关吗?如果有,为什么?
你能用你自己的话解释一下STA和MTA吗?
另外,什么是公寓线程,它们只与COM有关吗?如果有,为什么?
当前回答
COM线程模型称为“单元”模型,其中初始化的COM对象的执行上下文与单个线程(单线程单元)或多个线程(多线程单元)相关联。在这个模型中,COM对象一旦在一个单元中初始化,就在其运行期间是该单元的一部分。
STA模型用于非线程安全的COM对象。这意味着它们不处理自己的同步。它的一个常见用途是UI组件。因此,如果另一个线程需要与对象交互(例如按表单中的按钮),则消息将被编组到STA线程上。windows窗体消息泵送系统就是一个例子。
如果COM对象可以处理自己的同步,那么可以使用MTA模型,其中允许多个线程与对象交互,而不需要编组调用。
其他回答
Side note: If you are using some PowerShell 2.0 snap-ins, you need to launch PowerShell version 3 or greater with -MTA option to use them. PowerShell 2 apartment model is MTA versus later versions use STA as default. Other point is bitness. Normal calls in apartment are not marshalled (direct calls), so if your caller is x64 then callee must be also x64. Only way around this is to use remote procedure call (RPC), which add huge amount of overhead (spawn a new 32-bit process to load snap-in DLL and query result by some means).For developer: always publish type library - it make your COM object discovery and usage much easier! Every interface should be public and unique - implementation can be proprietary or open source.
另一种情况
例子:
IStorage_vtbl** reference; // you got it by some means of factory
public unsafe int OpenStorage(char* pwcsName, IStorage pstgPriority, uint grfMode, char** snbExclude, uint reserved, IStorage* ppstg)
{
IStorage_vtbl** @this = (IStorage_vtbl**)reference;
IStorage_vtbl* vtbl = *@this;
if (vtbl == null)
throw new InvalidComObjectException();
Delegate genericDelegate = Marshal.GetDelegateForFunctionPointer(vtbl->method_6, typeof(delegate_6));
delegate_6 method = (delegate_6)genericDelegate;
return method(@this, pwcsName, pstgPriority, grfMode, snbExclude, reserved, ppstg);
}
这段代码只是为COM子系统的实际调用添加了“This”指针 那么,这个调用是打开IStorage STA或MTA的实例吗?
每个承载COM或OLE控件的EXE都定义了它的单元状态。单元状态默认为STA(对于大多数程序应该是STA)。
STA -所有OLE控件必须位于STA中。STA意味着你的com对象必须总是在UI线程上操作,不能传递给其他线程(就像MFC中的任何UI元素一样)。但是,您的程序仍然可以有许多线程。
MTA -你可以在程序中的任何线程上操作COM对象。
调用COM对象dll的代码(例如,读取私有数据文件)可能在用户界面中正常工作,但却神秘地挂在服务上。原因是。net 2.0的用户界面假设是STA(线程安全的),而服务假设是MTA((在此之前,服务假设是STA)。必须为服务中的每个COM调用创建一个STA线程会增加大量开销。
根据我的理解,“Apartment”是用来保护COM对象不受多线程问题的影响。
If a COM object is not thread-safe, it should declare it as a STA object. Then only the thread who creates it can access it. The creation thread should declare itself as a STA thread. Under the hood, the thread stores the STA information in its TLS(Thread Local Storage). We call this behavior as that the thread enters a STA apartment. When other threads want to access this COM object, it should marshal the access to the creation thread. Basically, the creation thread uses messages mechanism to process the in-bound calls.
如果一个COM对象是线程安全的,它应该声明为一个MTA对象。MTA对象可以被多线程访问。
COM线程模型称为“单元”模型,其中初始化的COM对象的执行上下文与单个线程(单线程单元)或多个线程(多线程单元)相关联。在这个模型中,COM对象一旦在一个单元中初始化,就在其运行期间是该单元的一部分。
STA模型用于非线程安全的COM对象。这意味着它们不处理自己的同步。它的一个常见用途是UI组件。因此,如果另一个线程需要与对象交互(例如按表单中的按钮),则消息将被编组到STA线程上。windows窗体消息泵送系统就是一个例子。
如果COM对象可以处理自己的同步,那么可以使用MTA模型,其中允许多个线程与对象交互,而不需要编组调用。