在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记 - 小众知识

在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记

2023-02-10 01:13:44 苏内容
  标签:
阅读:2880

有关调用实时(JIT)调试而不是此对话框的详细信息,

请参见此消息的结尾。


************** 异常文本 **************

System.Threading.ThreadStateException: 在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记。

   在 System.Windows.Forms.Clipboard.SetDataObject(Object data, Boolean copy, Int32 retryTimes, Int32 retryDelay)

   在 System.Windows.Forms.Clipboard.Clear()

   在 DHUIGetData.DHUIForm.MainProcessFun(String msg) 位置 B:***.cs:行号 232

   在 DHUIGetData.DHUIForm.GetMYL***(String filename) 位置 B:***.cs:行号 438

   在 DHUIGetData.DHUIForm.<StartGet***>b__46_0() 位置 B:***.cs:行号 432

   在 System.Threading.Tasks.Task.Execute()

--- 引发异常的上一位置中堆栈跟踪的末尾 ---

   在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

   在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

   在 System.Runtime.CompilerServices.TaskAwaiter.GetResult()

   在 DHUIGetData.DHUIForm.<StartGetMYL>d__46.MoveNext() 位置 B:***.cs:行号 430

--- 引发异常的上一位置中堆栈跟踪的末尾 ---

   在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()



************** 已加载的程序集 **************

mscorlib

    程序集版本:4.0.0.0

    Win32 版本:4.7.3056.0 built by: NET472REL1

    基本代码:file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/mscorlib.dll

----------------------------------------

DHUIGetData

    程序集版本:1.0.0.0

    Win32 版本:1.0.0.0

    基本代码:file:///B:/SueseVS/CS/WorkTools/DHUIGetData/bin/Debug/DHUIGetData.exe

----------------------------------------

System.Windows.Forms

    程序集版本:4.0.0.0

    Win32 版本:4.7.3056.0 built by: NET472REL1

    基本代码:file:///C:/windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms/v4.0_4.0.0.0__b77a5c561934e089/System.Windows.Forms.dll

----------------------------------------

System

    程序集版本:4.0.0.0

    Win32 版本:4.7.3056.0 built by: NET472REL1

    基本代码:file:///C:/windows/Microsoft.Net/assembly/GAC_MSIL/System/v4.0_4.0.0.0__b77a5c561934e089/System.dll

----------------------------------------

System.Drawing

    程序集版本:4.0.0.0

    Win32 版本:4.7.3056.0 built by: NET472REL1

    基本代码:file:///C:/windows/Microsoft.Net/assembly/GAC_MSIL/System.Drawing/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll

----------------------------------------

System.Configuration

    程序集版本:4.0.0.0

    Win32 版本:4.7.3056.0 built by: NET472REL1

    基本代码:file:///C:/windows/Microsoft.Net/assembly/GAC_MSIL/System.Configuration/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll

----------------------------------------

System.Core

    程序集版本:4.0.0.0

    Win32 版本:4.7.3056.0 built by: NET472REL1

    基本代码:file:///C:/windows/Microsoft.Net/assembly/GAC_MSIL/System.Core/v4.0_4.0.0.0__b77a5c561934e089/System.Core.dll

----------------------------------------

System.Xml

    程序集版本:4.0.0.0

    Win32 版本:4.7.3056.0 built by: NET472REL1

    基本代码:file:///C:/windows/Microsoft.Net/assembly/GAC_MSIL/System.Xml/v4.0_4.0.0.0__b77a5c561934e089/System.Xml.dll

----------------------------------------

System.Windows.Forms.resources

    程序集版本:4.0.0.0

    Win32 版本:4.7.3056.0 built by: NET472REL1

    基本代码:file:///C:/windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms.resources/v4.0_4.0.0.0_zh-Hans_b77a5c561934e089/System.Windows.Forms.resources.dll

----------------------------------------

mscorlib.resources

    程序集版本:4.0.0.0

    Win32 版本:4.7.3056.0 built by: NET472REL1

    基本代码:file:///C:/windows/Microsoft.Net/assembly/GAC_MSIL/mscorlib.resources/v4.0_4.0.0.0_zh-Hans_b77a5c561934e089/mscorlib.resources.dll

----------------------------------------


************** JIT 调试 **************

要启用实时(JIT)调试,

该应用程序或计算机的 .config 文件(machine.config)的 system.windows.forms 节中必须设置

jitDebugging 值。

编译应用程序时还必须启用

调试。


例如:


<configuration>

    <system.windows.forms jitDebugging="true" />

</configuration>


启用 JIT 调试后,任何未经处理的异常

都将被发送到在此计算机上注册的 JIT 调试程序,

而不是由此对话框处理。





在可以调用 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



解决方法1:

(网上都是这种方法,由于该程序有多个线程同时在运行,不知有没有影响,所以没试这种办法的可行性)

既然问题是出在了“将当前线程设置为单线程单元(STA)模式”这块儿,所以就从这块入手,通过将线程的 ApartmentState 属性设置为ApartmentState 枚举值之一,可以控制所创建的单元的类型。

其中:

STA:Thread 将创建并进入一个单线程单元;

MTA:Thread 将创建并进入一个多线程单元;

Unknown:尚未设置 ApartmentState 属性。

代码如下:

  1. Thread recvThread=new Thread(new ParameterizedThreadStart(recvThreadProc));
  2. recvThread.SetApartmentState(ApartmentState.STA);
  3. recvThread.Start(commSock);

解决方法2:

创建一个委托,然后异步调用该委托

(1)在派生类中重写时,将异步消息分派到同步上下文。

  1. //创建SynchronizationContext对象,用于跨线程刷新控件
  2. public SynchronizationContext _syncContext = null;
  3. ...
  4. {
  5. ...
  6. _syncContext.Post(ExportSettingEndMethod, (object)settingInfo);
  7. ...
  8. }
  9. ....
  10. //将异步消息分派到同步上下文。
  11. public void ExportSettingEndMethod(object obj)
  12. {
  13. RefreshExportSettingEndEvent?.Invoke(obj);
  14. }

 

(2)把调用SaveFileDialog对象的函数放到endExportMethod函数里面调用。

 ru4.communicatThread.RefreshExportSettingEndEvent += endExportMethod;


扩展阅读
相关阅读
© CopyRight 2010-2021, PREDREAM.ORG, Inc.All Rights Reserved. 京ICP备13045924号-1