1. 程式人生 > 實用技巧 >C# 在可以呼叫 OLE 之前,必須將當前執行緒設定為單執行緒單元(STA)模式。請確保您的 Main 函式帶有 STAThreadAttribute 標記

C# 在可以呼叫 OLE 之前,必須將當前執行緒設定為單執行緒單元(STA)模式。請確保您的 Main 函式帶有 STAThreadAttribute 標記

  單元是程序內部具有相同執行緒訪問要求的物件的邏輯容器bai。同一單元中的所有物件都可以接收從該單元中的任何執行緒發出的呼叫。.NET Framework 不使用單元,託管物件自己負責以執行緒安全的方式使用所有共享資源。
  由於 COM 類使用單元,因此公共語言執行庫需要在 COM interop 的情況下呼叫 COM 物件時建立並初始化一個單元。託管執行緒可以建立並進入只允許有一個執行緒的單執行緒單元 (STA) 或者包含一個或多個執行緒的多執行緒單元 (MTA)。通過將執行緒的 ApartmentState 屬性設定為 ApartmentState 列舉值之一,可以控制所建立的單元的型別。由於給定執行緒只能初始化 COM 單元一次,因此在第一次呼叫非託管程式碼之後就不能更改單元型別。


成員定義:

STA:Thread 將建立並進入一個單執行緒單元。
MTA:Thread 將建立並進入一個多執行緒單元
Unknown:尚未設定 ApartmentState 屬性。

解決辦法兩種:
1) 在Main入口新增STAThread的Attribute

1 [STAThread]
2 static void Main()

2)

1 Thread app = new Thread(new ParameterizedThreadStart(ShowWindow));
2 app.ApartmentState = ApartmentState.STA;
3 //也可以
4 Thread newThread = new
Thread(new ThreadStart(ThreadMethod)); 5 newThread.SetApartmentState(ApartmentState.MTA);

例如:

 1 static void Main()
 2 {
 3   Thread newThread =
 4   new Thread(new ThreadStart(ThreadMethod));
 5   newThread.SetApartmentState(ApartmentState.MTA);
 6   // The following line is ignored since
 7   // ApartmentState can only be set once.
8   newThread.SetApartmentState(ApartmentState.STA); 9   Console.WriteLine("ThreadState: {0}, ApartmentState: {1}", 10   newThread.ThreadState, newThread.ApartmentState); 11   newThread.Start(); 12   // Wait for newThread to start and go to sleep. 13   Thread.Sleep(300); 14   try 15   { 16     // This causes an exception since newThread is sleeping. 17     newThread.SetApartmentState(ApartmentState.STA); 18   } 19   catch(ThreadStateException stateException) 20   { 21     Console.WriteLine("\n{0} caught:\n" + 22     "Thread is not in the Unstarted or Running state.", 23     stateException.GetType().Name); 24     Console.WriteLine("ThreadState: {0}, ApartmentState: {1}", 25     newThread.ThreadState, newThread.GetApartmentState()); 26   } 27 } 28 static void ThreadMethod() 29 { 30   Thread.Sleep(1000); 31 }