Wpf: Win32Exception (0x80004005): Not enough quota is available to process this command.

Created on 10 Dec 2018  路  11Comments  路  Source: dotnet/wpf

  • .NET Core Version: 3.0 Preview1
  • Windows version: Windows 10 / 7 SP1
  • Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes

    Problem description:

We sometimes get an Win32Exception (0x80004005) report from end-user' device, but we can't determine what happed at that time.

Actual behavior:

We sometimes get a feedback from the end-user that the app freezes at that moment when the exception is thrown.

System.ComponentModel.Win32Exception (0x80004005): Not enough quota is available to process this command.
   at MS.Win32.UnsafeNativeMethods.PostMessage(HandleRef hwnd, WindowMessage msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Interop.HwndTarget.UpdateWindowSettings(Boolean enableRenderTarget, Nullable`1 channelSet)
   at System.Windows.Interop.HwndTarget.UpdateWindowPos(IntPtr lParam)
   at System.Windows.Interop.HwndTarget.HandleMessage(WindowMessage msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Interop.HwndSource.HwndTargetFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

Expected behavior:

There is no such an exception.

Minimal repro:

Note that we still can't figure out all the reproduction, but I find a simple procedure to reproduce it.

  1. Launch a malicious app sending message to the target WPF app continuously;
  2. The WPF app will get the Win32Exception (0x80004005).

Most helpful comment

I found out that sInce .NET 4.7 this happens pretty randomly on locks, I initially thought my problem was caused by deadlocks but it was caused by this. the reason for this to happen is using the same synchronization object in one method that has await keyword and in another that doesn't. Lets say you got method without await on button click and the other one with await that executes as some kind of delayed response. If you click button 2-3 times everything will be okay, but if you click it repeatedly 5-15, it will freeze the app and eventually throw 'not enough quota'. Fix for this is to make the other method async, without changing any logic. I recently debugged this scenario extensively and I am sure it is not caussed by my code.

All 11 comments

Message queues have a limit described in the documentation for PostMessage. Flooding an application with window messages is expected to cause this exception. This is by design.

BTW, this will happen on WPF on .NET Framework as well.

@vatsan-madhavan So, what's the recommended way to avoid this kind of app crash?

An application architecture that hits that 10000 message limit would need to be changed, I鈥檓 afraid. Also, see But then we ran into problems when we started posting 10,000 messages per second.

This kind of bug report is observed in other UI technologies as well. We hear about this either as a bug report or a crash report now and then, and we usually recommend looking into the application architecture and finding out why the message queue is flooding rapidly.

WPF has a flag that you could use to aid in such a diagnosis. Please take a look at BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailure. Setting this to Throw can bring the problem to your attention as soon as it happens, and allow you to diagnose it accurately. Also take a look at Reset, but I wouldn't recommend using Reset as the default or as a replacement for diagnosing the underlying problem.

When you set it to Throw, set the debugger to catch the exception in Dispatcher.OnRequestProcessingFailure and puzzle out why the queue is full from there. Since the message queue is a kernel mode component, you can only get indirect clues to what is going on.

[Additional debugging tips courtesy of my colleague Sam Bent]

@vatsan-madhavan I also met this issue in .net framework 4.6.1, and i can't find this flag :BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailure in 4.6.1

That flag doesn鈥檛 exist in 4.6.1. It was introduced in 4.7.1.

Thanks @vatsan-madhavan for the detailed information, it's always nice to learn something every day.

I'm going to close this issue since it seems that this issue is by design (and unrelated to WPF specifically). @walterlv if you think that is wrong and there is actually a fundamental issue with WPF, please reply and we can continue the discussion.

@stevenbrix Thanks for your reply.
I'll try to set the BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailure flag to Reset to avoid this app crash on machines that has net471 runtime. After we migrating our product to .NET Core 3 we can use this flag ignoring machine runtime version.
So if you have some other recommended method to solve this issue in .NET Framework 4.7 or lower, I'm very glad to share it to others.
Thanks again.

I found out that sInce .NET 4.7 this happens pretty randomly on locks, I initially thought my problem was caused by deadlocks but it was caused by this. the reason for this to happen is using the same synchronization object in one method that has await keyword and in another that doesn't. Lets say you got method without await on button click and the other one with await that executes as some kind of delayed response. If you click button 2-3 times everything will be okay, but if you click it repeatedly 5-15, it will freeze the app and eventually throw 'not enough quota'. Fix for this is to make the other method async, without changing any logic. I recently debugged this scenario extensively and I am sure it is not caussed by my code.

I found out that sInce .NET 4.7 this happens pretty randomly on locks, I initially thought my problem was caused by deadlocks but it was caused by this. the reason for this to happen is using the same synchronization object in one method that has await keyword and in another that doesn't. Lets say you got method without await on button click and the other one with await that executes as some kind of delayed response. If you click button 2-3 times everything will be okay, but if you click it repeatedly 5-15, it will freeze the app and eventually throw 'not enough quota'. Fix for this is to make the other method async, without changing any logic. I recently debugged this scenario extensively and I am sure it is not caussed by my code.

Could you please attach the solution which reproduces the behavior?

@rvnlord I would like to see a solution that reproduces the behavior too.

Was this page helpful?
0 / 5 - 0 ratings