在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式
转载自:http://blog.163.com/smhily_min/blog/static/75206226201092011444205/
程序之前运行正常,我只是在一个事件中定义了做了如下操作,程序抛出此异常
private void OnExportPlan(object sender, EventArgs e) { try { if (null != ExportPlan) { Cursor = Cursors.WaitCursor; saveFileDialog1.Filter = "(Excel2003).xls|*.xls|(Excel2007).xlsx|*.xlsx"; if (DialogResult.OK == saveFileDialog1.ShowDialog()) { mExportFilePath = saveFileDialog1.FileName; Application.DoEvents(); ExportPlan(this, null); } } } finally { Cursor = Cursors.Default; } }
查看MSDN,有如下说明:
单元是进程内部具有相同线程访问要求的对象的逻辑容器。同一单元中的所有对象都可以接收从该单元中的任何线程发出的调用。.NET Framework 不使用单元,托管对象自己负责以线程安全的方式使用所有共享资源。
由于 COM 类使用单元,因此公共语言运行库需要在 COM interop 的情况下调用 COM 对象时创建并初始化一个单元。托管线程可以创建并进入只允许有一个线程的单线程单元 (STA) 或者包含一个或多个线程的多线程单元 (MTA)。通过将线程的ApartmentState 属性设置为ApartmentState 枚举值之一,可以控制所创建的单元的类型。由于给定线程只能初始化 COM 单元一次,因此在第一次调用非托管代码之后就不能更改单元类型。
成员定义:
STA:Thread 将创建并进入一个单线程单元。
MTA:Thread 将创建并进入一个多线程单元
Unknown:尚未设置 ApartmentState 属性。
解决办法两种:
1) 在Main入口添加STAThread的Attribute
[STAThread]
static void Main()
2)
Thread app = new Thread(new ParameterizedThreadStart(ShowWindow));
app.ApartmentState = ApartmentState.STA;
//也可以
Thread newThread = new Thread(new ThreadStart(ThreadMethod));
newThread.SetApartmentState(ApartmentState.MTA);
转载请注明原创地址:http://www.cnblogs.com/winzheng/archive/2008/12/02/1345656.html
例如:
static void Main()
{
Thread newThread =
new Thread(new ThreadStart(ThreadMethod));
newThread.SetApartmentState(ApartmentState.MTA);
// The following line is ignored since
// ApartmentState can only be set once.
newThread.SetApartmentState(ApartmentState.STA);
Console.WriteLine("ThreadState: {0}, ApartmentState: {1}",
newThread.ThreadState, newThread.ApartmentState);
newThread.Start();
// Wait for newThread to start and go to sleep.
Thread.Sleep();
try
{
// This causes an exception since newThread is sleeping.
newThread.SetApartmentState(ApartmentState.STA);
}
catch(ThreadStateException stateException)
{
Console.WriteLine("\n{0} caught:\n" + "Thread is not in the Unstarted or Running state.", stateException.GetType().Name);
Console.WriteLine("ThreadState: {0}, ApartmentState: {1}",
newThread.ThreadState, newThread.GetApartmentState());
}
}
static void ThreadMethod()
{
Thread.Sleep();
}
http://www.cnblogs.com/winzheng/archive/2008/12/02/1345656.html
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
实际上我自己在使用的时候
Thread newThread =new Thread(new ThreadStart(ThreadMethod)); newThread.SetApartmentState(ApartmentState.MTA);
用的是这个,但是还是会报错,反而使用
newThread.SetApartmentState(ApartmentState.STA);
的时候到正常运行,不知道具体的原因,仅供大家参考。
发现还有这么一篇文章页用到了这个设置的东西,有兴趣的可以看一下: