Link:
Could you explain STA and MTA?
STA: Single-Thread Apartment, 中文叫单线程套间。就是在COM库初始化的时候创建一个内存结构,然后让它和调用CoInitialize的线程相关联。这个内存结构针对每个线程都会有一个。支持STA的COM对象只能在创建它的线程里被使用,其它线程如果再创建它就会失败。
MTA: Mutil-Thread Apartment,中文叫多线程套间。COM库在进程中创建一个内存结构,这个内存结构在整个进程中只能有一个,然后让它和调用CoInitializeEx的线程相关联。支持MTA的COM对象可以在任意线程里被使用。多有针对它的调用都会被封装成为消息。
STA (单线程单元) | MTA |
Windows NT 3.51引入 | Windows NT 4.0 引入 |
只允许一个实例线程访问组件,不需要考虑多个线程访问实例变量的问题,因为这种保护是由COM特性实现的 | 多个线程可以同时访问组件 |
COM对象不是线程安全,需要在注册表中把注册键ThreadingModel设置为Apartment | COM对象线程安全,ThreadingModel设置为Free。值Both用于不考虑单元类型的线程安全的COM对象 |
其实STA和MTA是COM规定的一套线程模型,用于保障多线程情况下你的组件代码的同步。比如说有一个COM对象它内部有一个静态变量 gHello,那么这个对象无论生成多少实例对于gHello在内存中只能有一份,那么如果有两个不同的实例在两个线程里面同时去读写它,就有可能出错,所以就要就要有种机制进行同步保护,STA或者MTA就是这种机制。
.NET支持两种线程模型: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线程时,CLR会在该AppDomain中创建一个apartment和thread(从属于该apartment)。如果是创建MTA线程,CLR会检查该AppDomain是否存在一个存放MTA的apartment,如果存在仅创建该线程到该MTA中,否则就创建一个MTA和thread(从属于该apartment)。
我们可以设置线程的属性。例如 t.ApartmentState = ApartmentState.STA;
线程的使用区别:
我们应该仅仅在访问STA-based 的COM组件时才使用STA线程模式。可以在注册表的HKEY_CLASSES_ROOT/CLSID/{Class ID of the COM component} /InProcServer32 下查看到该COM的线程模式。如果该值是Apartment,则说明该COM只能以STA模式运行。其他的值有Free(MTA),Both(STA+MTA),Single(只能在一个单一的线程中执行)。
其他情况下,我们应该使用MTA的线程,虽然需要我们费心线程间资源的同步问题。
每个Thread都有一个关于ApartmentState的属性,可以把它设置为:STA或者MTA,或者UNKNOWN。
当你想指定工程的启动窗口的时候,你需要在该窗口类中申明一个Main()方法,并为这个方法设置[STAThread]属性。
详细信息,清查阅MSDN中关于Threading和COM Interop和COM+ Apartment Model的文章:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguidnf/html/cpconmanagedunmanagedthreading.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguidnf/html/cpconadvancedcominterop.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cossdk/htm/pgservices_synchronization_8703.asp
二:
[STAThread]是Single Thread Apartment单线程套间的意思,是一种线程模型,用在程序的入口方法上
(在C#和VB.NET里是Main()方法),来指定当前线程的ApartmentState 是STA。用在其他方法上不产生影响。
在aspx页面上可以使用AspCompat = "true" 来达到同样的效果。这个属性只在 Com Interop 有用,
如果全部是 managed code 则无用。简单的说法:[STAThread]指示应用程序的默认线程模型是单线程单元 (STA)。
启动线程模型可设置为单线程单元或多线程单元。如果未对其进行设置,则该线程不被初始化。也就是说如果你用的.NET Framework,
并且没有使用COM Interop,一般不需要这个Attribute。其它的还有MTA(多线程套间)、Free Thread(自由线程)。
单线程套间,简单来说所有对于单线程套间中对象的访问都是通过消息来传递的,所以同一时间只有一个线程能够访问单线程套间中的对象。
三:
C#中,[STAThread]代表什么意思?如何用?
Single Thread Apartment
>Why is STAThread required?
it changes the apartment state of the current thread to be single threaded
>Single Thread Apartment vs MultiThread Apartment?
Correct: With the STAThread attribute, you will be interacting with COM processes in a
"Single Threading Apartment" model. Without it, you will be interacting with COM processes
in the "Multiple Threading Apartment" model.
> so why do I need it....or why would I want it at some point?
You may want to interact with a COM process in a MTA model for performance reasons. You may
want to interact with a COM process in a STA model because of a design requirement. For example,
to use the Windows clipboard (System.Windows.Forms.Clipboard) you must be calling from a thread
running in a STA. If the calling thread was started by your application you can set the ApartmentState
(System.Threading.ApartmentState) before starting, but if you want to use the clipboard from your a
pplication's main thread, you need to use the System.STAThread attribute on your Main method.
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-YWan5iZxUTZ5UGOxQDZ0QDM1gTNhR2NmRTZ2IGMiFDO2EmZm9CX0EzLchDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLzM3Lc9CX6MHc0RHaiojIsJye.gif)
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> 1
private void CopyImages()
2
{
3
Word.Application app = null;
4
Word.Document doc = null;
5
6
app = new ApplicationClass();
7
8
try
9
{
10
object fileName = @"E:/A.doc";
11
doc = app.Documents.Open(ref fileName,ref missing,ref missing,ref missing,ref missing,ref missing,ref missing,ref missing,ref missing,ref missing,
12
ref missing,ref missing,ref missing,ref missing,ref missing,ref missing);
13
14
int count = doc.InlineShapes.Count;
15
for(int i=1;i<=count;i++)
16
{
17
doc.InlineShapes[i].Range.Copy();
18
19
if (Clipboard.GetDataObject() != null)
20
{
21
IDataObject data = Clipboard.GetDataObject();
22
23
if (data.GetDataPresent(DataFormats.Bitmap))
24
{
25
Image image = (Image)data.GetData(DataFormats.Bitmap,true);
26
image.Save("E://" + i.ToString() + ".jpg",System.Drawing.Imaging.ImageFormat.Jpeg);
27
}
28
else
29
30
lst_Items.Items.Add(doc.Name + ";无正确图片数据");
31
32
}
33
else
34
35
lst_Items.Items.Add(doc.Name + ";粘贴板为空");
36
37
}
38
39
}
40
catch(Exception ex)
41
42
lst_Items.Items.Add(doc.Name + "发生错误;" + ex.Message);
43
44
finally
45
46
if (doc != null)
47
doc.Close(ref missing,ref missing,ref missing);
48
if (app != null)
49
app.Quit(ref missing,ref missing,ref missing);
50