• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

如何解决C#异常:必须先将当前线程设置为单线程单元(STA)模式,然后才能进行OLE调用 ...

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

本文概述

 

如果你的应用程序运行一段代码, 该代码触发以下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上的此问题。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#数据结构二:顺序表Sequence List发布时间:2022-07-13
下一篇:
C#中字符串的处理发布时间:2022-07-13
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap