在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式

在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式

转载自:http://blog.163.com/smhily_min/blog/static/75206226201092011444205/

在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记。 只有将调试器附加到该进程才会引发此异常。

程序之前运行正常,我只是在一个事件中定义了做了如下操作,程序抛出此异常

 

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(300);
        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(1000);
    }
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);

的时候到正常运行,不知道具体的原因,仅供大家参考。

发现自己的博客上还有这么一篇文章页用到了这个设置的东西,有兴趣的可以看一下:

http://blog.csdn.net/xuehuic/article/details/6426284

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值