папки - wpf c# folderbrowserdialog




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

Я получаю следующее исключение при попытке использовать 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. 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.

Я широко гуглил эту проблему, и решения, которые все предлагают, похоже, [STAThreadAttribute] том, чтобы поместить [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;
    }
}

Я получаю исключение на fbd.ShowDialog ().


Насколько я знаю, атрибут STAThread должен находиться перед main.


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

Из STAThreadAttribute в MSDN :

Примените этот атрибут к методу точки входа (метод Main () в C # и 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);

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

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





folderbrowserdialog