zoukankan      html  css  js  c++  java
  • 如何解决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:UsersMyNameDesktopmyfile.json
    Console.WriteLine(selectedPath);

    有关此异常的更多信息, 我们也建议你阅读StackOverflow上的此问题。

    作者:阿笨

          【官方QQ一群:跟着阿笨一起玩NET(已满)】:422315558跟着阿笨一起玩NET

          【官方QQ二群:跟着阿笨一起玩C#(已满)】:574187616跟着阿笨一起玩C#

          【官方QQ三群:跟着阿笨一起玩ASP.NET(已满)】:967920586跟着阿笨一起玩ASP.NET

          【官方QQ四群:Asp.Net Core跨平台技术开发(可加入)】:806491485Asp.Net Core跨平台技术开

          【官方QQ五群:.NET Core跨平台开发技术(可加入)】:1036896405.NET Core跨平台开发技术

          【网易云课堂】:https://study.163.com/provider/2544628/index.htm?share=2&shareId=2544628

          【腾讯课堂】:https://abennet.ke.qq.com

          【51CTO学院】:https://edu.51cto.com/sd/66c64

          【微信公众号】:http://dwz.cn/ABenNET

  • 相关阅读:
    Android--多线程之Handler
    webkit-transition-
    结构体直接赋值
    shell 俄罗斯方块 杂记
    debian 开启daytime等服务 "xinetd"
    Linux中 etc/init.d “服务"
    <iOS>关于Xcode上的Other linker flags
    多线程总结
    git的使用与分支管理
    -ios项目中安装和使用CocoaPods
  • 原文地址:https://www.cnblogs.com/51net/p/15209954.html
Copyright © 2011-2022 走看看