cefsharp / CefSharp

.NET (WPF and Windows Forms) bindings for the Chromium Embedded Framework
http://cefsharp.github.io/
Other
9.82k stars 2.92k forks source link

Application Hangs when you show MessageBox in LostFocus event #2183

Closed ekalchev closed 6 years ago

ekalchev commented 6 years ago

This is easy to reproduce - I just added this lines of code to CefSharp.WinForms.Example.csproj BrowserTabUserControl.Designer.cs

this.urlTextBox.LostFocus += UrlTextBox_LostFocus;
private void UrlTextBox_LostFocus(object sender, System.EventArgs e)
{
    MessageBox.Show("test");
}

I am running the application in x86 mode. First you need to focus the Url TextBox and then click on the Browser control. It works fine if the new focused element is not the browser control.

What happens is the application hangs and you need to kill the process to continue. I can reproduce the same issue with CefGlue and it seems it is a issue with CEF not with C# wrappers but I still wanted to ask if someone knows why this happens and how to avoid it.

I have the same issue in my WPF application which uses WinForms browser control.

Thanks.

jankurianski commented 6 years ago

I couldn't reproduce this problem in master. What version are you using?

I don't know why it happens but my guess is that it is related to how MessageBox.Show() blocks the calling thread and pumps the message loop, causing a bug in CEF.

Have you tried showing the message box in a BeginInvoke? This will wait until the message loop pumps again, causing different timing. Example:

        private void UrlTextBox_LostFocus(object sender, System.EventArgs e)
        {
            BeginInvoke(new Action(() => {
                MessageBox.Show("test");
            }));
        }
ekalchev commented 6 years ago

Hey thanks for your response. I can reproduce this with latest version from master (both CefGlue and CefSharp).

.Net version 4.6.1 Visual Studio 2015 Windows 10

The new focus MUST BE browser control and you need to run CefSharp.WinForms.Example. Steps are:

  1. Click inside UrlTextBox
  2. Click on the browser control

It is 100% reproducible on multiple machines I tried. Yes, using Dispatcher.InvokeAsync is a workaround for this issue but it doesn't solve it.

jankurianski commented 6 years ago

My computer has the same specs as yours and I still cannot reproduce using master. I see the message box "test" come up, I can click OK and then the browser and WinForms controls still respond fine. I can do it multiple times. I am running CefSharp.WinForms.Example by starting with debugger in Visual Studio 2015. It works fine in Win32' andx64`.

Here is the diff of the changes I made to BrowserTabUserControl.Designer.cs: https://gist.github.com/jankurianski/60f5098e9fbeef0de81b39b5aa8c957d

Perhaps the order of the event being attached makes a difference. Can you post a gist of your exact changes?

ekalchev commented 6 years ago

I am reproducing this with your gist. You need to lose focus and your new focus MUST BE the browser control. Steps are

  1. Click on Url Text box to gain focus
  2. Click on Browser Control Result: I see the MessageBox but the application is not responding and the cursor is stuck in loading state. The only thing I can do is to kill the process.

I am reproducing this on my home computer, both x64 and Win32 and on multiple computers at my work - it is reproducible on every computer I tried so far.

jankurianski commented 6 years ago

By "Click on Browser Control" - do you mean click inside the web browser window, i.e. on any web content? If so, that is what I am doing.

ekalchev commented 6 years ago

Yes, anywhere on the web page

amaitland commented 6 years ago

The GotFocus and LostFocus events are low-level focus events that are tied to the WM_KILLFOCUS and WM_SETFOCUS Windows messages. Typically, the GotFocus and LostFocus events are only used when updating UICues or when writing custom controls. Instead the Enter and Leave events should be used for all controls except the Form class, which uses the Activated and Deactivate events. For more information about the GotFocus and LostFocus events, see the WM_KILLFOCUS and WM_KILLFOCUS topics.

In general you should be using the Leave event for any sort of control that's not the Form.

https://msdn.microsoft.com/en-us/library/system.windows.forms.control.lostfocus(v=vs.110).aspx

Do not attempt to set focus from within the Enter, GotFocus, Leave, LostFocus, Validating, or Validated event handlers. Doing so can cause your application or the operating system to stop responding. For more information, see the WM_KILLFOCUS topic.

See the CAUTION section in https://msdn.microsoft.com/en-us/library/system.windows.forms.control.lostfocus(v=vs.110).aspx

If you dig into MessageBox.Show you'll see the last thing it does it attempt to refocus the control. http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/MessageBox.cs,495

With the sample code you provided what happens when you press the X to close the Form when urlTextBox has focus? Can you even close the form? Additionally can you pass focus to another program?

Using the Leave event may fire sufficiently late enough in the message processing that you don't get stuck in a loop. It's still not recommended.

Closing this as invalid as it goes against Microsoft recommendations.

wewake4 commented 6 years ago

Hi, I am facing the same problem. I have a property grid with int value

> int m_DisplayInt = 50;                    // some initialization
> 
>       [Description("sample hint1")]             // sample hint1
>       [Category("Category1")]                   // Category that I want
>       [DisplayName("Int for Displaying")]       // I want to say more, than just DisplayInt
>       public int DisplayInt
>       {
>         get { return m_DisplayInt; }
>         set { m_DisplayInt = value; }
>       }

During running the application, delete the integer value and click on the cefsharp browser. property grid produces a validation message that 'int is not valid' and Application freezes. Not able to close the message box. It happens only when clicked on cefsharp browser.