C# STA和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文档,将图片信息复制到粘贴板中,然后从粘贴板中取得图片信息,再保存到本地目录中。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.Office.Interop.Word;
using System.Windows.Forms;
using System.Drawing;
namespace ConsoleApplication1
{
class STAANDMTA
{
static void Main()
{
Thread t = new Thread(new ThreadStart(CopyImages));
t.ApartmentState = ApartmentState.STA;
t.Start();
} private static void CopyImages()
{
Microsoft.Office.Interop.Word.Application app = null;
Microsoft.Office.Interop.Word.Document doc = null; object missing = System.Reflection.Missing.Value; app = new Microsoft.Office.Interop.Word.Application(); try
{
object fileName = @"E:\A.doc";
doc = app.Documents.Open(ref fileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing, ref missing); int count = doc.InlineShapes.Count;
for (int i = ; i <= count; i++)
{
doc.InlineShapes[i].Range.Copy();//复制到粘贴板 if (System.Windows.Forms.Clipboard.GetDataObject() != null)
{
IDataObject data = Clipboard.GetDataObject(); if (data.GetDataPresent(DataFormats.Bitmap))
{
Image image = (Image)data.GetData(DataFormats.Bitmap, true);
image.Save("E:\\" + i.ToString() + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
else
{
//lst_Items.Items.Add(doc.Name + ";无正确图片数据");
}
}
else
{
//lst_Items.Items.Add(doc.Name + ";粘贴板为空");
}
} }
catch (Exception ex)
{
//lst_Items.Items.Add(doc.Name + "发生错误;" + ex.Message);
}
finally
{
if (doc != null)
doc.Close(ref missing, ref missing, ref missing);
if (app != null)
app.Quit(ref missing, ref missing, ref missing);
}
}
}
}
说明:
如果在某个按钮的事件中,直接调用该方法,那么界面将变得没有响应。所以我们需要考虑使用多线程来解决这个问题。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线程为需要维护内部隐藏的窗口类
和消息队列而增加的。
C# STA和MTA线程设置的更多相关文章
- 选择目录,选择文件夹的COM组件问题。在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记。 只有将调试器附加到该进程才会引发此异常。
异常: 在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式.请确保您的 Main 函数带有 STAThreadAttribute 标记. 只有将调试器附加到该进程才会引发此异常. ...
- 在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式
在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式 转载自:http://blog.163.com/smhily_min/blog/static/75206226201092011 ...
- c# Clipboard.SetDataObject(bmp1) 在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记。 只有将调试器附加到该进程才会引发此异常
c# Clipboard.SetDataObject(bmp1) 在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式.请确保您的 Main 函数带有 STAThreadAttri ...
- 异常错误:在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式
最近做一个蛋疼的东西就是C#调用windows API 来操作一个摄像头,自动处理一些东西.要用到剪切板复制 粘贴功能,即 Clipboard.SetDataObject(filedic, true) ...
- C#“必须先将当前线程设置为单个线程单元(STA)模式方可进行OLE调用”异常解决方案
关于这类问题网上搜索会有很多解决方案,但基本的意思都相差不大,大致问题出于启用线程时调用类似剪贴板Clipboard.SetDataObject出错,我把我的测试代码展现下: 解决方案:只需将thre ...
- 在可以调用OLE之前,必须将当前线程设置为单线程单元(STA)模式,请确保您的Main函数带有STAThreadAttribute
导入导出功能,在调用ShowDialog时的错误,解决办法如下: WinForm窗体的入口点: /// <summary> /// 应用程序的主入口点. /// </summary& ...
- .NET4.5可以给所有线程设置默认的Culture了
How to set CurrentCulture for all threads in a domain in .NET 4.5 Before .NET 4.5 if we wanted to se ...
- tomcat 7.0 最大连接数和线程设置
部署项目时需要根据服务器配置调整连接数 <Connector port="8080" protocol="HTTP/1.1"URIEncoding=&qu ...
- work,i/o最小线程设置
设置work i/o最小线程有两种方式1.通过配置文件设置,影响所有iis部署程序(待验证)2.通过程序代码设置,iis上部署的程序互不影响int minWorker, minIOC; //Get t ...
随机推荐
- Linux经常使用的命令-权利管理命令-权利管理命令chmod
指令名字:chmod 命令英语的意图:change the permissions mode of a file 凡路径命令:/bin/chmod 语法:chmod [{ugoa}{+-=}{rwx} ...
- 标签(Tag)的各种设计方案
标签(Tag)的各种设计方案 首先,标签(Tag)是什么? 我的理解:用来具体区分某一类内容的标识,和标签类似的一个概念是分类(Category),有一个示例可以很好的区分它们两个,比如人类分为:白种 ...
- listener.ora中PLSExtPro 和ExtProc的作用(转)
默认安装时,会安装一个PL/SQL外部程序(ExtProc)条目在listener.ora中,是oracle为调用外部程序默认配置的监听,它的名字通常是ExtProc或PLSExtProc,但一般不会 ...
- Learn Python More
0, 看了一个python项目开源源码, 才知道现在这点python知识实在是弱爆了.. 尼玛就像学了2500个常用汉字, 然后要去理解"楚辞".. 代码如下, 解释一点一点从网上 ...
- XML概要
早在两年前,我一直听说XML,但是,只是没有时间去研究它.也不知道它的作用,花了一些时间最近几天来学习他们的语言.是XML的一些简介希望能对各位同学有所帮助: XML是eXtensible Ma ...
- Lampda或Linq中的SqlFunctions.StringConvert()
要使用 Lampda或Linq中的SqlFunctions.StringConvert(), 需要引用命名空间using System.Data.Objects.SqlClient, 该函数可进行模拟 ...
- C#格式化字符串中转义大括号“{}”
原文:C#格式化字符串中转义大括号"{}" 今天,用C#写程序操作Excel,读取单元格内容根据所需格式生成字符串,使用String.Format(string format,ob ...
- DevExpress XtraReports 入门四 创建 Web 报表
原文:DevExpress XtraReports 入门四 创建 Web 报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助更多的人不会像我这 ...
- poj 2828 线段树
http://poj.org/problem?id=2828 学到的思维: 1.变化的或者后来的优先影响前面的,那么从最后一个往前看,最后一个就成了 确定的, 而且后来的也能够确定----假设从前往后 ...
- applet授权数字签名
一.压缩你的class类文件为jar包 1.如果你的须要压缩的类文件存在的包为:cn.mbq.test1和cn.mbq.test2 2.进入你的classes文件夹,在DOS窗体中运行命令:jar c ...