Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#:从另一个线程显示UI线程上的对话框_C#_Winforms_Multithreading_Dialog - Fatal编程技术网

C#:从另一个线程显示UI线程上的对话框

C#:从另一个线程显示UI线程上的对话框,c#,winforms,multithreading,dialog,C#,Winforms,Multithreading,Dialog,我是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 (

我是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;
    }
}
此方法将始终从与表单所有者不同的线程调用。问题是,当我执行这段代码时,“Form1”冻结和“SaveFileDialog”不会显示

您有什么线索可以帮助我从独立线程显示对话框吗?

试试这个:

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

让它看起来像这样:

    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;
        }
    }
公共字符串AskSaveFile(){
if(this.invokererequired){
返回(字符串)调用(newfunc(()=>AskSaveFile());
}
否则{
var sfd=new SaveFileDialog();
sfd.Filter=“Fichiers txt(*.txt)|*.txt | Tous les Fichiers(*.*)|*.”;
sfd.FilterIndex=1;
sfd.RestoreDirectory=true;
返回sfd.ShowDialog()==DialogResult.OK?sfd.FileName:null;
}
}
如果仍然出现死锁,请确保使用调试器的Debug+Windows+Threads窗口,并查看UI线程正在执行的操作。除非UI线程处于空闲状态并泵送消息循环,否则无法完成Control.Invoke()。等待工作线程完成总是会导致死锁


也认为这种代码是有风险的,用户可能不希望这个对话框在UI线程所拥有的窗口中弹出或键入时突然出现并意外关闭它。

不工作:“ASKSaveFILE”需要返回字符串。如果我用“EndInvoke”等待结果,我也会遇到同样的问题(“Form1”冻结)。。。所以这可以奏效。。。。哦,是的,主线程将执行此。。但是你的意思是你的主线程正在做一些不同的事情,不能使用吗?相信我,在我的应用程序中,我在不同的线程中使用了这些代码,它可以工作。。。汉斯:你的评论是对我的还是对马修的?你是对的,第一部分是有效的,它显示了对话。但我找到了解决办法。我已经将调用该方法的线程设置为“STA”,现在是这个线程为您执行方法“sfd.ShowDialog()”。C#编译器不允许您编写不保证返回值始终设置的代码。谢谢,这对我来说很有效。我在FolderBrowserDialog中使用了它