.NET Threading Model(STA and MTA)
最近看了一些多线程方面的咚咚,说说自己的认识,抛砖引玉。
参考资料:
http://www.yesky.com/20010207/158097.shtml
http://www.ftponline.com/china/XmlFile.aspx?ID=242
http://research.microsoft.com/~chadv/java_com2.htm
http://blogs.msdn.com/jfoscoding/archive/2005/04/07/406341.aspx
.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的线程,虽然需要我们费心线程间资源的同步问题。
示例:
我现在想在一个windows form的程序中实现从某个word文档复制图片并保存的方案。
具体是:打开word文档,将图片信息复制到粘贴板中,然后从粘贴板中取得图片信息,再保存到本地目录中。
说明:(本来是放在代码下面的,无奈POST之后就被代码挡住不显示了
)
如果在某个按钮的事件中,直接调用该方法,那么界面将变得没有响应。所以我们需要考虑使用多线程来解决这个问题。Thread t = new Thread(new TheardStart(CopyImages); t.Start();
如果是这样,则程序会发生错误.。要么显示出现异常,要么没异常但是Clipboard为空,取不到任何数据!为什么呢?
因为Word.Application 是Automation并且STA-Based,不能在没有指定ThreadApartment的线程中被调用。所以导致了各种错误,所以需要在t.Start();前面加上t.Apartment = ApartmentState.STA;这样就完全正常了。
对于MTA的多线程我们就见的比较多了,不再举例了。
另外一点不明白,我监视任务管理器发现,我在执行Thread t = new Thread(new TheardStart(CopyImages);t.Apartment = ApartmentState.STA; t.Start();之后该程序的进程中线程数从3个增加到6个,如果创建的是MTA的线程则只增加1。我的理解是STA线程为需要维护内部隐藏的窗口类和消息队列而增加的。
下面是实现方法:

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
}
参考资料:
http://www.yesky.com/20010207/158097.shtml
http://www.ftponline.com/china/XmlFile.aspx?ID=242
http://research.microsoft.com/~chadv/java_com2.htm
http://blogs.msdn.com/jfoscoding/archive/2005/04/07/406341.aspx
.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的线程,虽然需要我们费心线程间资源的同步问题。
示例:
我现在想在一个windows form的程序中实现从某个word文档复制图片并保存的方案。
具体是:打开word文档,将图片信息复制到粘贴板中,然后从粘贴板中取得图片信息,再保存到本地目录中。
说明:(本来是放在代码下面的,无奈POST之后就被代码挡住不显示了
如果在某个按钮的事件中,直接调用该方法,那么界面将变得没有响应。所以我们需要考虑使用多线程来解决这个问题。Thread t = new Thread(new TheardStart(CopyImages); t.Start();
如果是这样,则程序会发生错误.。要么显示出现异常,要么没异常但是Clipboard为空,取不到任何数据!为什么呢?
因为Word.Application 是Automation并且STA-Based,不能在没有指定ThreadApartment的线程中被调用。所以导致了各种错误,所以需要在t.Start();前面加上t.Apartment = ApartmentState.STA;这样就完全正常了。
对于MTA的多线程我们就见的比较多了,不再举例了。
另外一点不明白,我监视任务管理器发现,我在执行Thread t = new Thread(new TheardStart(CopyImages);t.Apartment = ApartmentState.STA; t.Start();之后该程序的进程中线程数从3个增加到6个,如果创建的是MTA的线程则只增加1。我的理解是STA线程为需要维护内部隐藏的窗口类和消息队列而增加的。
下面是实现方法:
1
private void CopyImages()2

{3
Word.Application app = null;4
Word.Document doc = null;5
6
app = new ApplicationClass();7
8
try9

{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
finally45

{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
}