Подтвердить что ты не робот

Исключение при использовании FolderBrowserDialog

Я получаю следующее Исключение при попытке использовать FolderBrowserDialog: System.Threading.ThreadStateException: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process.

У меня много проблем с Googled, и решения, которые, как кажутся, кажутся, должны ставить [STAThreadAttribute] выше метода Main, удалять всю dll из папки Debug или использовать метод Invoke. Я пробовал все это, и я все равно получаю то же исключение.

Здесь код:

public partial class Form1 : Form
{
    public event EventHandler ChooseLocationHandler = null;

    public string DestFolder
    {
        set { textBox1.Text = value; }
        get { return textBox1.Text; }
    }

    public Form1()
    {
        InitializeComponent();
    }

    private void ChooseLocationButton_Click(object sender, EventArgs e)
    {
        if (ChooseLocationHandler != null)
            ChooseLocationHandler(this, e);
    }
}

И в моем презентаторе есть следующее:

public partial class Presenter
{
    Form1 myForm;
    public Presenter()
    {
        myForm = new Form1();
        myForm.ChooseLocationHandler += ChooseLocationHandler;
        myForm.Show();
    }

    public void ChooseLocationHandler(object obj, EventArgs e)
    {
        Form1 sender = (Form1)obj;

        FolderBrowserDialog fbd = new FolderBrowserDialog();
        fbd.RootFolder = System.Environment.SpecialFolder.MyComputer;
        fbd.ShowNewFolderButton = true;
        if (fbd.ShowDialog() == DialogResult.Cancel)
            return;

        sender.DestFolder = fbd.SelectedPath;
    }
}

Я получаю Exception на fbd.ShowDialog().

4b9b3361

Ответ 1

Поток является STA или MTA, он не может быть указан только для одного метода, поэтому атрибут должен присутствовать в точке входа.

От STAThreadAttribute в MSDN:

Применить этот атрибут к методу точки входа (метод Main() в С# и Visual Basic). Это не влияет на другие методы.

Если этот код вызывается из вторичного потока, у вас есть 3 варианта:

ВАЖНОЕ ПРИМЕЧАНИЕ: Выполнение (как вам кажется) кода System.Windows.Forms внутри потока MTA неразумно, некоторые функции, такие как открытые диалоги файлов (не только папка), требуют, чтобы поток MTA работал.

Изменение вашей квартиры вторичной нити

Если вы сами создаете поток (и не используете специфику MTA), вы можете просто изменить его квартиру перед запуском:

var t = new Thread(...);
t.SetApartmentState(ApartmentState.STA);

 

Создание потока только для него

Если вы не контролируете создание потоков, вы можете сделать это во временном потоке:

string selectedPath;
var t = new Thread((ThreadStart)(() => {
    FolderBrowserDialog fbd = new FolderBrowserDialog();
    fbd.RootFolder = System.Environment.SpecialFolder.MyComputer;
    fbd.ShowNewFolderButton = true;
    if (fbd.ShowDialog() == DialogResult.Cancel)
        return;

    selectedPath = fbd.SelectedPath;
}));

t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
Console.WriteLine(selectedPath);

 

Вызов в другом (STA) потоке

Если ваш основной поток также содержит код System.Windows.Forms, вы можете вызвать в нем цикл сообщений для выполнения кода:

string selectedPath = null;
Form f = // Some other form created on an STA thread;
f.Invoke(((Action)(() => {
    FolderBrowserDialog fbd = new FolderBrowserDialog();
    fbd.RootFolder = System.Environment.SpecialFolder.MyComputer;
    fbd.ShowNewFolderButton = true;
    if (fbd.ShowDialog() == DialogResult.Cancel)
        return;

    selectedPath = fbd.SelectedPath;
})), null);
Console.WriteLine(selectedPath);

Ответ 2

Атрибут STAThread должен находиться перед основным, насколько я знаю.

Ответ 3

Это исправило мою проблему.   [STAThread]   static void Main()

Просто вопрос: почему Microsoft не может сделать вещи простыми? Они пытаются отвратить людей к некоторому кодированию?

Ответ 5

Так же просто, как показано ниже:

using System.Windows.Forms;
namespace fileConverterBaset64
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)

Добавьте команду [STAThread] перед вашим основным методом. Вот оно, это будет работать.

Ответ 6

Теперь проверьте все dll в справочнике и удалите dll не использовать.

Это было невероятно. Я никогда не мог предположить, что эти DLL вызывают эту проблему.