wpf icon indicating copy to clipboard operation
wpf copied to clipboard

Spell Check very slow and causes UI to become unresponsive

Open LaughingJohn opened this issue 3 years ago • 5 comments

.NET Version: I tried this with .Net Framework 4.5.2, 4.7.2, 4.8 and .Net (Core) 6.0. Windows version: Windows 11 Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes

Hi,

The spell checking is really slow in our Application (.Net 4.7.2) and causes the UI to become unresponsive and essentially unusable until the spell check is complete. This affects both the text box and the rich textbox.

To investigate this I created a simple test project with a single textbox with spelling enabled (SpellCheck.IsEnabled="True") bound to a string property. At start-up I load the string property with text and the problem is observed. Once the spell check has finished the UI becomes responsive again.

The problem seems worse the more misspelt words there are in the text and the longer the text is (tested with "Lorum Ipsum" text). It is also made worse if there are multiple text boxes/rich text boxes with spelling enabled on the same window (as is the case in our actual application).

My colleague claims to have also observed high CPU, but in my testing CPU was around 8% (laptop with Core I9 & 32GB). I wonder whether it is more to do with the UI thread being blocked.

I tried the switch: AppContext.SetSwitch(@"Switch.System.Windows.Controls.DoNotAugmentWordBreakingUsingSpeller", true); but this didn't seem to make much, if any, difference.

I know it's a completely different beast, but I did some testing with the same text in Word and of course it was very responsive. This appears similar to #3350.

This has been reported by our customers.

Thanks

LaughingJohn avatar Feb 10 '22 15:02 LaughingJohn

@LaughingJohn Could you please provide a sample repro for this issue?

singhashish-wpf avatar Feb 22 '22 16:02 singhashish-wpf

Attached. This is .Net 6.0. Same happens in .Net 4.5. I appreciate that Lorum Ipsum is a kind of worse case scenario, but this is causing issues in a real life application with normal English text.

TestSpellCheckedNet6.zip

LaughingJohn avatar Mar 10 '22 17:03 LaughingJohn

Any news on this? We're still seeing issues..

LaughingJohn avatar Jun 30 '23 12:06 LaughingJohn

Still seeing this issue!

LaughingJohn avatar Apr 10 '25 14:04 LaughingJohn

The issue can still be seen with .NET9, too.

I believe that in some cases this can even cause "FailFast" crashes, though I could not reproduce this myself.

CoreCLR Version: 8.0.23.53103
.NET Version: 8.0.0
Description: The application requested process termination through System.Environment.FailFast.
Message: Nicht behebbarer Systemfehler.
Stack:
   at System.Environment.FailFast(System.String)
   at System.Windows.Documents.SpellerStatusTable.MarkErrorRange(System.Windows.Documents.ITextPointer, System.Windows.Documents.ITextPointer)
   at System.Windows.Documents.Speller.ScanTextSegment(ISpellerSegment, System.Object)
   at System.Windows.Documents.WinRTSpellerInterop.EnumTextSegments(Char[], Int32, EnumSentencesCallback, EnumTextSegmentsCallback, System.Object)
   at System.Windows.Documents.Speller.ScanRange(System.Windows.Documents.ITextPointer, System.Windows.Documents.ITextPointer, Int64)
   at System.Windows.Documents.Speller.OnIdle(System.Object)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(System.Object)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at MS.Internal.CulturePreservingExecutionContext.Run(MS.Internal.CulturePreservingExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
   at System.Windows.Application.RunDispatcher(System.Object)
   at System.Windows.Application.RunInternal(System.Windows.Window)
....

stefanegli avatar Sep 16 '25 12:09 stefanegli