winforms C#:在UI线程上显示来自另一个线程的对话框

qlckcl4x  于 2023-06-24  发布在  C#
关注(0)|答案(2)|浏览(201)

我是C#的新手,但我已经做了很多Java。我的问题是我试图从非UI线程打开“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;
    }
}

此方法将始终从与拥有Form的线程不同的线程调用。问题是,当我执行这段代码时,“Form1”冻结,“SaveFileDialog”不显示。
你有一些线索,以帮助我显示对话框从一个独立的线程?

f0brbegy

f0brbegy1#

让它看起来像这样:

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窗口,并查看UI线程正在执行的操作。控件.Invoke()无法完成,除非UI线程处于空闲状态并正在执行Application.Run()。如果不是,比如等待工作线程完成,那么这段代码总是会死锁。
从UI可用性的Angular 来看,也要考虑这种代码是有风险的。用户可能不希望这个对话框会突然出现,并且可能在UI线程拥有的窗口中鼠标或键盘输入时意外地关闭它。

gv8xihay

gv8xihay2#

试试这个:

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;
    }
}

相关问题