如何解决C#异常(必须先将当前线程设置为单线程单元(STA)模式,然后才能进行OLE调用,请确保你的Main函数已在其上标记了STAThreadAttribute)
本文概述
- 异常示例
- 解
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上的此问题。
编码愉快!
推荐阅读
- PHP 7.3提供的主要功能
- 如何在Symfony 4中将Twig Extension注册为不带自动接线的服务
- 如何在Symfony 4中使用服务检索项目的根目录和其他容器参数
- 前端开发人员可以通过这些技巧来帮助避免倦怠
- 如何解决(解决方案)Google的Blockly Future Programmers Game(Bird Level)
- sync-diff数据比对工具
- 一文搞懂linux进程
- docker容器网络配置
- 云原生动态追踪