Massive use of BitmapCache leads to UCEERR_RENDERTHREADFAILURE
- Dominant language
- C#
- Stars
- 7.7k
- Forks
- 1.3k
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 61
Description
### Description
When BitmapCache is enabled for ~5000 UIElements, the rendering thread fails.
### Reproduction Steps
A small project with a button to reproduce the problem: https://github.com/reejk/WpfBitmapCacheRenderThreadFail.
Or just create about 5000 UIElements with `CacheMode = BitmapCache`
### Expected behavior
The render thread does not fail.
### Actual behavior
```
System.Runtime.InteropServices.COMException (0x88980406): UCEERR_RENDERTHREADFAILURE (0x88980406)
at System.Windows.Media.Composition.DUCE.Channel.SyncFlush()
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 System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
```
### Regression?
_No response_
### Known Workarounds
To work around the problem, it is possible to write a MarkupExtension to limit BitmapCache usage.
### Impact
_No response_
### Configuration
Reproduces on .NET 6 and .NET Framework 4.8
### Other information
The root cause is `WGXERR_WIN32ERROR` at `BaseRT.cpp:145`.
```cpp.
IFCW32(m_hrgnInvalidRegion = CreateRectRgn(0, 0, 0, 0, 0, 0));
```
Where `WGXERR_WIN32ERROR` because `CreateRectRgn` returns `NULL` due to the 10000 GDI object count limit being exceeded.
Probably to fix the problem it is possible to just ignore `BitmapCache` to avoid exceeding the limit or do what is written a few lines above:
```cpp
// Future: Do not allocate for non-mapped targets.
//
// Right now we allocate for all classes derived from CBaseRenderTarget,
// but not all of them need this functionality.
```
Contributor guide
Assessment
This issue has not been assessed yet.