从另一个对话框调用时,OpenFileDialog会冻结

时间:2014-01-24 17:37:23

标签: c# winforms

我有表格:SplashscreenSearchNewEntry

Program.cs启动Splashscreen,检查一些参数,并在成功(检查用户名,权限等)后打开Search表单。从那里我可以拨打NewEntry表格。

因为SplashscreenMain()函数调用的主要表单,一旦关闭,应用程序就会关闭(这是预期的行为)。
所以我所做的就是从Splashscreen开始,我将Search表格作为对话框隐藏Splashscreen,等待Search关闭。一旦它关闭,我也关闭Splashscreen,这一切似乎都有意义。从Search表单我打开NewEntry表单(点击按钮)也作为对话框(我不希望用户来回点击并创建多个NewEntry窗口)。< / p>

今天我必须添加一个允许用户选择文件的功能。作为一个明显的选择,我使用了OpenFileDialog。但是只要我调用.ShowDialog()方法,整个应用就会冻结。

我在这里和其他网站上看过Windows Forms GUI hangs when calling OpenFileDialog.ShowDialog()OpenFileDialog.ShowDialog() freezing application c#以及其他一些帖子,当我几乎失去了希望时,我遇到了这个http://wishmesh.com/2011/06/call-to-openfiledialog-or-savefiledialog-hangs-or-freezes/
我在[STAThread]函数

上设置了Main()属性

一个特别感兴趣的点是: 对于OpenFileDialog,必须显式设置ShowHelp属性。
还有 ......它们不必设置为true,只需将它们初始化为true或false。

因此,当我将ShowHelp设置为true时,对话框会显示(使用无用的“帮助”按钮)。

进一步的研究表明,当我在(new OpenFileDialog()).ShowDialog();内或Program.cs内执行Splashscreen时,它的效果很好;但是,从对话框调用时,会有一个挂起(没有ShowHelp)。此外,来自MessageBox ...

Dialog显示正常

有没有办法让这项工作?或者我应该以不同的方式管理我的窗户? 例如,将Search作为主启动窗口,然后在窗口显示之前,将Splashscreen作为对话框调用,如果失败,只需关闭主窗口?但是,我如何处理NewEntry才能展示OpenFileDialogFolderBrowserDialog

感谢。

3 个答案:

答案 0 :(得分:3)

最让我担心的部分是当你说你有SplashScreen等待搜索关闭时。如果你这样做

if (search.ShowDialog() == DialogResult.OK)
{
    Show();
}

然后你冻结了SplashScreen的UI线程。由于它是主要形式,因此不太可能按预期工作。我建议将代码改为此。

Hide(); // Hides SplashScreen
Search search = new Search();
search.ParentForm = this;
search.Show(); // Show Search without freezing SplashScreen thread

ParentForm是我添加到搜索中的公共变量。这应该是私有的,并且应该通过getter / setter访问,但这会使代码示例保持简短。

public partial class Search: Form
{
    public SplashScreen ParentForm;
    ...
}

接下来,您需要添加一个处理程序来处理搜索表单关闭。这将显示SplashScreen。

private void Form2_FormClosed(object sender, FormClosedEventArgs e)
{
    ParentForm.Show();
}

进行这些更改后,OpenFileDialog显示正常工作。

答案 1 :(得分:2)

如果在program.cs中,您正在呼叫:Application.Run(new splashscreen());,如果是我,我会这样做,以便您可以在启动画面关闭后打开多个表单。

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        new splashscreen().ShowDialog(); 
        Application.Run(new Search());
    }
}

这将显示启动画面,然后一旦加载了所有内容,您就可以打开搜索表单并关闭启动画面,而不必调用ShowDialog()。 (您必须致电application.End()以结束申请。)

答案 2 :(得分:1)

我真的很感谢你对此事的帮助。

总而言之,我创建了Form1Form2来测试一些代码,这就是我所拥有的(只有相关部分):

// Form1:
void Button1Click(object sender, EventArgs e)
{
    Form2 f2=new Form2();
    this.Hide();
    f2.Show(this);
}

// Form2:
void Form2Load(object sender, EventArgs e)
{
    if (this.Owner==null) throw new ArgumentException("This window must be called with the Owner property set!");
    // or just ignore, or show a MessageBox and close, or use your imagination...
}

void Form2FormClosed(object sender, FormClosedEventArgs e)
{
    // sanity check...
    if (this.Owner!=null && !this.Owner.Visible) this.Owner.Show();
}

因此,当我调用Form2时,我首先隐藏当前表单并使用Show()的重载,该重载需要1个参数并设置Form2的{​​{1}}属性。或者,我可以拨打Owner,然后拨打f2.Owner=this;

然后当f2.Show();关闭/之后,我检查所有者是否已设置并显示该表单。

现在回到最初的问题,这里是Form2里面的内容:

Program.cs

现在if ((new Splashscreen()).ShowDialog() == DialogResult.OK) Application.Run(new Search()); 仅显示Search是否随Splashscreen一起返回,而当DialogResult.OK关闭时,应用程序会正常退出。

感谢您的帮助。
这节省了我很多时间。

P.S。
我希望我能将这两个答案标记为答案,然后掷硬币并随机标记一个。