调用OpenFileDialog.ShowDialog()时,Windows窗体GUI挂起

Kag*_*age 6 .net c# user-interface winforms

我的项目是一个三层架构项目,与后端的WCF服务进行通信.当后端能够从服务获取数据时,它使用发布 - 订阅通知业务层,而后者通知GUI层.

我使用Visual Studios设计器为我的UI设计添加了一个OpenFileDialog.按钮事件处理程序调用ShowDialog消息.但是,一旦我单击按钮,整个UI就会挂起.

谷歌搜索了一下,我发现使用委托是处理这样的任务的首选方式.但是,无论是否有代表,问题仍然存在.

目前我的代码如下所示:

private void bOpen_Click(object sender, EventArgs e)
{
    Func<Image> del = delegate
    {
        OpenFileDialog d = new OpenFileDialog();
        if (d.ShowDialog() == DialogResult.OK)
        {
            return Image.FromFile(d.FileName);
        }

        return null;
    };

    Invoke(del);
}
Run Code Online (Sandbox Code Playgroud)

我来自Java世界,所以我并不熟悉C#UI编程的复杂性.

我在这里缺少什么?

Kag*_*age 9

我似乎已经解决了将[STAThread]属性添加到main方法的问题.一旦我在调试器中运行程序,我被告知要这样做 - 我之前没有这样做,因为我经常从Windows运行服务,而客户端经常从Windows运行.

[STAThread]
public static void Main(string[] args)
{
    GUI gui = new GUI();
    gui.ShowDialog();
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释一下到底发生了什么


小智 9

openFileDialog1->ShowHelp = true;
Run Code Online (Sandbox Code Playgroud)

我把这行放在我的代码中然后问题解决了.


Han*_*ant 7

这往往是一个环境问题,当您使用OpenFileDialog时,很多shell扩展会被加载到您的进程中.一个行为不端的人很容易搞砸你的程序.那里有很多不好的东西.

调试这很困难,你需要一个非托管调试器,因为这些shell扩展是非托管代码.在死锁后进入中断时,您可能能够从调用堆栈中分辨出某些内容.需要Windows调试符号,启用Microsoft符号服务器.但最有效的方法是使用SysInternals的AutoRuns实用程序.首先禁用所有未由Microsoft生成的shell扩展.然后开始重新启用那些你不能一个接一个的生活.

并且,正如您所发现的那样,这些shell扩展期望在STA线程上运行,并且当它们没有得到它时会失败.程序的UI线程必须始终是STA,也支持剪贴板和拖放以及各种控件,如WebBrowser.通常由Main()方法的[STAThread]属性自动处理,由项目模板放在那里.和Application.Run()调用,需要实现STA合同.你没有僵局.