C #: Показать диалог в потоке пользовательского интерфейса из другого потока - PullRequest
9 голосов
/ 27 августа 2011

Я новичок в C #, но я сделал много Java. Вот моя проблема: я пытаюсь открыть «SaveFileDialog» из потока, который не является потоком пользовательского интерфейса.

Это именно то, что я пытаюсь сделать:

public partial class Form1: Form
{
    public string AskSaveFile()
    {
        var sfd = new SaveFileDialog();
        sfd.Filter = "Fichiers txt (*.txt)|*.txt|Tous les fichiers (*.*)|*.*";
        sfd.FilterIndex = 1;
        sfd.RestoreDirectory = true;
        DialogResult result = (DialogResult) Invoke(new Action(() => sfd.ShowDialog(this)));
        if(result == DialogResult.OK)
        {
            return sfd.FileName;
        }

        return null;
    }
}

Этот метод всегда будет вызываться из потока, отличного от того, кто владеет формой. Проблема заключается в том, что при выполнении этого кода «Form1» зависает, а «SaveFileDialog» не отображается.

У вас есть подсказка, чтобы помочь мне показать диалог из независимой ветки?

Ответы [ 2 ]

11 голосов
/ 27 августа 2011

Сделайте так, чтобы это выглядело так:

    public string AskSaveFile() {
        if (this.InvokeRequired) {
            return (string)Invoke(new Func<string>(() => AskSaveFile()));
        }
        else {
            var sfd = new SaveFileDialog();
            sfd.Filter = "Fichiers txt (*.txt)|*.txt|Tous les fichiers (*.*)|*.*";
            sfd.FilterIndex = 1;
            sfd.RestoreDirectory = true;
            return sfd.ShowDialog() == DialogResult.OK ? sfd.FileName : null;
        }
    }

Если вы все еще получаете тупик, тогда обязательно используйте окно Debug + Windows + Threads отладчика и посмотрите, что делает поток пользовательского интерфейса.Control.Invoke () не может завершиться, если поток пользовательского интерфейса не используется и не закачивает цикл сообщений.Ожидание завершения рабочего потока всегда приводит к взаимоблокировке.

Также учтите, что этот вид кода опасен, пользователь может не ожидать, что это диалоговое окно внезапно отобразится и случайно закроет его при наведении курсора или вводе клавиатуры.окна, принадлежащие потоку пользовательского интерфейса.

6 голосов
/ 27 августа 2011

Попробуйте это:

public partial class Form1: Form
{
    public string AskSaveFile()
    {
        if (this.InvokeRequired)
        {
            Invoke( new MethodInvoker( delegate() { AskSaveFile(); } ) );
        }
        else
        {
            var sfd = new SaveFileDialog();
            sfd.Filter = "Fichiers txt (*.txt)|*.txt|Tous les fichiers (*.*)|*.*";
            sfd.FilterIndex = 1;
            sfd.RestoreDirectory = true;
            if(sfd.ShowDialog() == DialogResult.OK) return sfd.FileName; 
        }               
        return null;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...