简体   繁体   English

Windows Forms GUI 在调用 OpenFileDialog.ShowDialog() 时挂起

[英]Windows Forms GUI hangs when calling OpenFileDialog.ShowDialog()

my project a three tier architecture project talking to a WCF service in the backend.我的项目是一个三层架构项目,它与后端的 WCF 服务通信。 When the backend is able to fetch data from the service, it notifies the business layer using publish-subscribe, which in return notifies the GUI layer.当后端能够从服务中获取数据时,它会使用发布-订阅通知业务层,然后通知 GUI 层。

I have added an OpenFileDialog to my UI design using Visual Studios designer.我使用 Visual Studios 设计器在我的 UI 设计中添加了一个 OpenFileDialog。 A button event handler calls the ShowDialog message.按钮事件处理程序调用 ShowDialog 消息。 However, once I click the button, the whole UI hangs.但是,一旦我单击按钮,整个 UI 就会挂起。

Having googled around a bit, I found out that using delegates is the preferred way to handle tasks like this.搜索了一下,我发现使用委托是处理此类任务的首选方式。 However, with nor without delegate the problem persists.但是,无论有没有委托,问题仍然存在。

Currently my code looks like this:目前我的代码如下所示:

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

I'm coming from the Java world, so I'm not really familiar with the intricacies of C# UI programming.我来自 Java 世界,所以我不太熟悉 C# UI 编程的复杂性。

Anything I'm missing here?我在这里缺少什么吗?

openFileDialog1->ShowHelp = true;

I put this line in my code then the problem was solved.我将这一行放在我的代码中,然后问题就解决了。

I seem to have solved the problem adding the [STAThread] Attribute to the main method.我似乎已经解决了将 [STAThread] 属性添加到 main 方法的问题。 I was told to do so once I ran the program in a debugger - which I hadn't done before because I ran the service from Visual Studio and the client regularly from Windows.一旦我在调试器中运行程序,我就被告知要这样做——我以前没有这样做过,因为我从 Visual Studio 和客户端定期从 Windows 运行服务。

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

Can anybody explain what exactly is going on though任何人都可以解释到底发生了什么

This tends to be an environmental problem, when you use OpenFileDialog a lot of shell extensions get loaded into your process.这往往是一个环境问题,当您使用 OpenFileDialog 时,很多 shell 扩展会加载到您的进程中。 A misbehaving one can easily screw up your program.行为不端的人很容易搞砸你的程序。 There are a lot of bad ones out there.那里有很多坏人。

Debugging this is difficult, you need an unmanaged debugger since these shell extensions are unmanaged code.调试这很困难,您需要一个非托管调试器,因为这些 shell 扩展是非托管代码。 You might be able to tell something from the call stack when you break in after the deadlock.当您在死锁后闯入时,您可能能够从调用堆栈中分辨出一些东西。 Windows debugging symbols required, enable the Microsoft symbol server. Windows 需要调试符号,启用微软符号服务器。 But the most effective approach is to use SysInternals' AutoRuns utility.但最有效的方法是使用 SysInternals 的 AutoRuns 实用程序。 Start by disabling all of the shell extensions that were not produced by Microsoft.首先禁用所有不是由 Microsoft 生产的 shell 扩展。 Then start re-enabling the ones you cannot live without one by one.然后开始一一重新启用那些你不能没有的东西。

And, as you found out, these shell extension expect to run on an STA thread and fail miserably when they don't get it.而且,正如您所发现的,这些 shell 扩展期望在 STA 线程上运行,并且当他们没有得到它时会惨遭失败。 The UI thread of a program must always be STA, also to support the clipboard and drag-and-drop and various kinds of controls like WebBrowser.程序的UI线程必须始终是STA,还要支持剪贴板和拖放以及WebBrowser等各种控件。 Normally always taken care of automatically by the [STAThread] attribute on the Main() method, put there by the project template.通常总是由 Main() 方法上的 [STAThread] 属性自动处理,由项目模板放置在那里。 And the Application.Run() call, required to implement the STA contract.以及实现 STA 合约所需的 Application.Run() 调用。 Deadlock when you don't.当你不这样做时会出现死锁。

I believe the "delegate" prefered way actually refers to using a separate thread.我相信“委托”首选方式实际上是指使用单独的线程。 I'm gonna give you an example using BackgroundWorker.我会给你一个使用 BackgroundWorker 的例子。

It would look like this:它看起来像这样:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            m_Worker.DoWork += new DoWorkEventHandler(m_Worker_DoWork);
            m_Worker.ProgressChanged += new ProgressChangedEventHandler(m_Worker_ProgressChanged);
            m_Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_Worker_RunWorkerCompleted);
        }

        void m_Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            //Usually, used to update a progress bar
        }

        void m_Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //Usually, used to add some code to notify the user that the job is done.
        }

        void m_Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            //e.Argument.ToString() contains the path to the file
            //Do what you want with the file returned.
        }        

        private void bOpen_Click(object sender, EventArgs e)
        {
            OpenFileDialog d = new OpenFileDialog();
            if (d.ShowDialog() == DialogResult.OK)
            {
                m_Worker.RunWorkerAsync(d.FileName);    
            }            
        }

        BackgroundWorker m_Worker = new BackgroundWorker();
    }

Now, as for the reason your UI "hangs", it's because by default, your operation runs on the UI thread, so if you run something heavy the UI won't respond.现在,至于你的 UI “挂起”的原因,这是因为默认情况下,你的操作在 UI 线程上运行,所以如果你运行重的东西,UI 将不会响应。

I also met this problem.我也遇到了这个问题。 And I tried all the solution here and none can solve it.我在这里尝试了所有解决方案,但没有一个可以解决。 Then I change the target framework from.Net Framework 4.7 to 4.6.2, the problem solved...然后我把目标框架从.Net Framework 4.7改成4.6.2,问题解决了……

I think my problem is different, as none of the above solutions worked for me.我认为我的问题有所不同,因为上述解决方案都不适合我。

I wrote temporary code to set the OpenFileDialog.FileName property to something not null or empty string (it was empty string when the hang up occured), and I restarted my computer .我编写了临时代码来OpenFileDialog.FileName属性设置为不是 null或空字符串(挂断时它是空字符串),然后我重新启动了计算机 When I started up Visual Studio again, and ran it, it worked again without hanging up.当我再次启动 Visual Studio 并运行它时,它再次工作而没有挂断。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 OpenFileDialog.ShowDialog()在Silverlight中引发InvalidOperationException - OpenFileDialog.ShowDialog() raises InvalidOperationException in Silverlight 如何填充OpenFileDialog.ShowDialog方法 - How to shim OpenFileDialog.ShowDialog method openFileDialog.ShowDialog()未显示对话框 - openFileDialog.ShowDialog() didnt show dialog 为什么在单击ToolStrip按钮两次时抛出NullReferenceException - openFileDialog.showDialog()? - Why is a NullReferenceException thrown when a ToolStrip button is clicked twice - openFileDialog.showDialog()? C#OpenFiledialog.Showdialog给出错误CS1061 - C# OpenFiledialog.Showdialog giving error CS1061 我可以使WinForms OpenFileDialog.ShowDialog不产生主线程吗? - Can I make a WinForms OpenFileDialog.ShowDialog not yield the main thread? 调用OpenFileDialog.ShowDialog()后UI无法更新 - UI not getting updated after call to OpenFileDialog.ShowDialog() 调用弹出窗口的.ShowDialog()时,WPF应用程序关闭 - WPF application closes when calling `.ShowDialog()` of a popup windows Windows窗体:UI线程与Show()和ShowDialog()一起流动 - Windows Forms: UI threads flow with Show() and ShowDialog() 在 windows forms 中使用 OpenFileDialog 读取文本文件 - Reading a text file using OpenFileDialog in windows forms
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM