如何解決C#異常:必須先將當前線程設置為單線程單元(STA)模式,然后才能進行OLE調用,請確保你的Main函數已在其上標記了STAThreadAttribute


本文概述

 

如果你的應用程序運行一段代碼, 該代碼觸發以下ThreadStateException異常:

System.Threading.ThreadStateException:’必須先將當前線程設置為單線程單元(STA)模式, 然后才能進行OLE調用。確保你的Main函數上已標記STAThreadAttribute。僅當將調試器附加到進程時, 才會引發此異常。

在本文中, 我們將向你簡要說明如何防止此異常出現在WinForms項目中。

 

異常示例

在我們的項目中, 我們使用CefSharp庫, 該庫允許我們使用HTML, CSS和JavaScript創建桌面應用程序。它的功能之一是可以將C#類暴露給窗口中的JavaScript對象。我們具有以下類, 該類顯示用於保存文件的本機對話框(showOpenDialog函數):

using System; using CefSharp.WinForms; using System.IO; using System.Diagnostics; using System.Windows.Forms; using System.Threading; using System.Text; namespace MyApplication { class WindowsTools { // Declare a local instance of chromium and the main form in order to execute things from here in the main thread private static ChromiumWebBrowser _instanceBrowser = null; // The form class needs to be changed according to yours private static Form1 _instanceMainForm = null; public WindowsTools(ChromiumWebBrowser originalBrowser, Form1 mainForm) { _instanceBrowser = originalBrowser; _instanceMainForm = mainForm; } // When this method is called like this, it will throw the exception public void showOpenFile() { OpenFileDialog saveFileDialog1 = new OpenFileDialog(); saveFileDialog1.Filter = "JSON Files (*.json)|*.json"; saveFileDialog1.FilterIndex = 2; saveFileDialog1.RestoreDirectory = true; if (saveFileDialog1.ShowDialog() == DialogResult.OK) { } } } }

如果從JavaScript上下文(CefSharp線程)執行該函數, 則將觸發異常, 因為我們正在CefSharp的默認Apartment State內部運行代碼。

 

解決辦法

默認情況下, 主應用程序線程初始化為ApartmentState.MTA。將主應用程序線程的公寓狀態設置為ApartmentState.STA的唯一方法是將STAThreadAttribute屬性應用於入口點方法。在我們的例子中, 使用從CefSharp中注冊的類啟動OpenFileDialog的方法, 如果在不更改線程的單元狀態的情況下運行代碼, 將引發異常。

如果你不控制線程的創建(例如CefSharp), 則以下解決方案是最佳解決方案, 你可以創建一個臨時線程並在其中運行代碼:

using System.Threading; string selectedPath = ""; Thread t = new Thread((ThreadStart)(() => { OpenFileDialog saveFileDialog1 = new OpenFileDialog(); saveFileDialog1.Filter = "JSON Files (*.json)|*.json"; saveFileDialog1.FilterIndex = 2; saveFileDialog1.RestoreDirectory = true; if (saveFileDialog1.ShowDialog() == DialogResult.OK) { selectedPath = saveFileDialog1.FileName; } })); // Run your code from a thread that joins the STA Thread t.SetApartmentState(ApartmentState.STA); t.Start(); t.Join(); // e.g C:\Users\MyName\Desktop\myfile.json Console.WriteLine(selectedPath);

有關此異常的更多信息, 我們也建議你閱讀StackOverflow上的此問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



猜您在找 C#解決“System.Threading.ThreadStateException:“在可以調用 OLE 之前,必須將當前線程設置為單線程單元(STA)模式。請確保您的 Main 函數帶有 STAThreadAttribute 標記。 只有將調試程序附加到該進程才會引發此異常”的異常 在可以調用 OLE 之前,必須將當前線程設置為單線程單元(STA)模式,請確保您的Main函數帶有STAThreadAttribute標記。 多線程操作剪切板的時候。 解決“System.Threading.ThreadStateException:“在可以調用 OLE 之前,必須將當前線程設置為單線程單元(STA)模式。請確保您的 Main 函數帶有 STAThreadAttribute 標記。 只有將調試程序附加到該進程才會引發此異常”的異常 在可以調用OLE之前,必須將當前線程設置為單線程單元(STA)模式,請確保您的Main函數帶有STAThreadAttribute 選擇目錄,選擇文件夾的COM組件問題。在可以調用 OLE 之前,必須將當前線程設置為單線程單元(STA)模式。請確保您的 Main 函數帶有 STAThreadAttribute 標記。 只有將調試器附加到該進程才會引發此異常。 異常錯誤:在可以調用 OLE 之前,必須將當前線程設置為單線程單元(STA)模式 在可以調用 OLE 之前,必須將當前線程設置為單線程單元(STA)模式 在可以調用 OLE 之前,必須將當前線程設置為單線程單元(STA)模式 類中調用界面ActiveX控件報錯當前線程不在單線程單元中因此無法實例化 ActiveX 控件的解決辦法 當前線程不在單線程單元中,因此無法實例化 ActiveX 控件
 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM