fix: refine message loop handling to prevent blocking#1255
fix: refine message loop handling to prevent blocking#1255AlbertXingZhang wants to merge 3 commits intowebview:masterfrom
Conversation
|
Pls using |
|
I tried to follow the convention of this source file. It seems it just uses Windows APIs in Unicode version. |
|
Thanks for this PR. Isn't there a chance that this changed loop might waste a fair bit of CPU cycles? In any case, if it's not for long, it might be better than potentially blocking for an extensive period of time. Would be great if this also solves the issue where tests sometimes hang. The usage of |
|
Do you a particular environment where you can easily reproduce the issue? Would love to be able to test and verify |
|
I couldn't produce the issue constantly. But it did happen occasionally. I found it is blocked at |
|
After taking a closer look at this I have to admit that I don't quite understand how this can solve the issue. If we're just looping I just remembered that I had thought about this issue before and the solution I made in PR #766 was never merged. I believe the real solution is to post a message when WebView2 initialization completes/fails instead of just setting a flag. That way there's no doubt about whether there will be another message to process in the loop, and therefore won't get stuck. If you want to take a look at it then search for usage of |
|
If there is always at least one message in the message queue, I think you are right. The PR you mentioned might work but it is a different approach. This change just tries to fix the potential freezing issue for the current approach. I think this is a common way to wait for a task for a certain time without blocking GUI. |
|
In my environment, WebView2 calls our "controller completed" handler during the call to It might be worth adding log statements to the existing code and then run CI tests a few times to see when there might be a delay in messages causing On a side note, using the captured Adding Maybe I'm missing something because it's difficult for me to see how adding Oh, and one small change I spotted in your code is that you set |
|
Honestly, I don't know how GUI and its message queue work internally for Windows. Maybe only Microsoft knows. The bottom line for this change is giving a chance to check I saw |
|
I've been trying to experiment but sadly haven't gotten much closer to fixing the hangs. I'm however leaning toward believing that this code change can't actually resolve the issue because I don't believe that it has anything to do with the fact that If it really does in your case then I can't figure out why, but I would like to understand why before considering a merge. I have also made some observations that I believe justify my doubts. It's true that using Things I've tested:
Set-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\' -Name 'ProxyEnable' -Value 0
|
|
Thanks for this PR but unfortunately I can't clearly see a way to move forward with this, and will close it. It would be great if we could determine what the real issue is. The fact that |
|
Hi @SteffenL, I'm sorry for being late. I was looking for how Microsoft implement Application.DoEvents. I think we tried to implement the same thing here. Here are my findings:
As I mentioned before, I'm not an expert who knows Windows messages and message queues better than Microsoft. I just tried to do something similar to what Microsoft did for .NET in this PR. I hope it can solve the hanging issue. Actually, it does work for my case. |
|
Is there any way you can provide a minimal example where you can reproduce the issue? Does it occur with the C++ examples that are in this repository? |
|
Sorry, whenever I took my part from the original big project into a minimal repo, the issue never got reproduced. And the C++ examples in this repo don't have this issue either, at least on my computer. |
|
Is it a pure C++ project or is .NET involved in any way? |
|
The project is modularized. Although my module is written in pure C++, along with other modules written in WinForms and WPF, all of them coexist in the same process. And each module can call each other. So, my C++ dialog is shown from a Windows Form or a WPF window. |
|
I'm still trying to wrap my head around this. If you're mixing different UI frameworks within the same process, it seems reasonable to assume that you have an existing event/message loop somewhere in your app, possibly with their own special handling as you've shown in your earlier post. The webview library has a few places where it temporarily spins a loop even if you don't call If another loop ( In this case, maybe that could be alleviated by using However, only one message loop is supposed to be running at a time per thread, so it's difficult for me to really imagine why that can help. With that said, someone who integrates the webview library into an app with an existing UI framework might argue that the webview library is the one who is potentially stealing messages? If there's any cross-thread messaging and synchronization going on somewhere, maybe that could be a source of problems... Not quite sure. I'm also not sure if it'll help but:
How to create a message loopThis page shows how to create a message loop: MSG msg;
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}Here's another variant of this from Microsoft: https://learn.microsoft.com/en-us/windows/win32/learnwin32/window-messages#the-message-loop // Correct.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}That's pretty much how we do it. Another piece of documentation:
|
|
Sorry, it is very difficult to debug into the code. I could only use logs to locate the freezing cause before. When it froze, I remember I waited for a couple minutes but it never recovered. |
|
I guess you had log statements around all the I believe A call stack would be handy in this situation... What if you were to keep it running in a debugger, then when you notice that it's frozen, you just pause the program in the debugger and check the main thread's call stack? |
|
Sorry, I couldn't find the old logs about hanging currently. I can keep it running in a debugger but I'm not sure if I can capture the hanging issue on this computer. This issue is a mystery to me. It happened occasionally on some of our previous computers while it never happened on the others. |
|
I have observed similar behaviour with This is true for all platforms, but different for MSWebview2, which appears to need to navigate before it starts processing scripts (which I think includes the Weview JS script). Seeing that Also possibly contributing is @SteffenL The Windows CI tests hanging may also be related to them running in console mode instead of GUI mode. I have been working to resolve and normalise many higher level issues, and it would be good to remove them from the equation for this issue. @AlbertXingZhang - would you try out #1309 @SteffenL - CI tests are switched to GUI for Windows in #1312 (e23a91d, 6a3c84d) |
GetMessageWsometimes blocks the thread and freezes the program. This changes it to calling non-blockingPeekMessageWwithPM_NOREMOVEfirst and then callingGetMessageWonce there is a message available.