dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
6.92k stars 1.15k forks source link

COMException in SpellChecker #8772

Open Khaos66 opened 5 months ago

Khaos66 commented 5 months ago

Description

On some machines our app is logging this unhandled dispatcher exception a lot:

System.Runtime.InteropServices.COMException (0x8001010D): Die COM-Klassenfactory für die Komponente mit CLSID {7AB36653-1796-484B-BDFA-E74F1DB7C1DC} konnte aufgrund des folgenden Fehlers nicht abgerufen werden: 8001010d Ein ausgehender Aufruf kann nicht ausgeführt werden, da die Anwendung einen eingabe-synchronisierten Aufruf weiterleitet. (Ausnahme von HRESULT: 0x8001010D (RPC_E_CANTCALLOUT_ININPUTSYNCCALL)).
   bei MS.Internal.ReaderWriterLockSlimWrapper.ExecuteWithinLockInternal(Action lockAcquire, Action lockRelease, Object& result, Delegate criticalAction, Object[] args)
   bei MS.Internal.ReaderWriterLockSlimWrapper.WithWriteLock[T1,T2,TResult](Func`3 criticalAction, T1 arg1, T2 arg2, TResult& result)
   bei System.Windows.Documents.MsSpellCheckLib.SpellCheckerFactory.CreateSpellCheckerPrivate(String languageTag, Boolean suppressCOMExceptions)
   bei System.Windows.Documents.MsSpellCheckLib.SpellChecker.Init(Boolean shouldSuppressCOMExceptions)
   bei System.Windows.Documents.MsSpellCheckLib.SpellChecker.<>c__DisplayClass35_0.<ComprehensiveCheckImplWithRetries>b__1()
   bei System.Windows.Documents.MsSpellCheckLib.RetryHelper.TryExecuteFunction[TResult](Func`1 func, TResult& result, RetryPreamble preamble, List`1 ignoredExceptions, Int32 retries, Boolean throwOnFailure)
   bei System.Windows.Documents.MsSpellCheckLib.SpellChecker.ComprehensiveCheckImplWithRetries(String text, Boolean shouldSuppressCOMExceptions)
   bei System.Windows.Documents.WinRTSpellerInterop.SpellerSegment.EnumerateSuggestions()
   bei System.Windows.Documents.WinRTSpellerInterop.SpellerSegment.get_IsClean()
   bei System.Windows.Documents.Speller.ScanTextSegment(ISpellerSegment textSegment, Object o)
   bei System.Windows.Documents.WinRTSpellerInterop.EnumTextSegments(Char[] text, Int32 count, EnumSentencesCallback sentenceCallback, EnumTextSegmentsCallback segmentCallback, Object data)
   bei System.Windows.Documents.Speller.ScanRange(ITextPointer start, ITextPointer end, Int64 timeLimit)
   bei System.Windows.Documents.Speller.OnIdle(Object unused)
   bei System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   bei System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

Reproduction Steps

Our app is quite complex. It uses WPF only for the UI. It includes an ElementHost, that is included via COM.

Expected behavior

No exception

Actual behavior

COMException is thrown in preamble action, even though ignoredException includes COMException See https://github.com/dotnet/wpf/blob/63a9081957decc475c6fd9a6ccd960f4fda3dfbc/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/MsSpellCheckLib/Utils/RetryHelper.cs#L137

Regression?

No response

Known Workarounds

No response

Impact

No response

Configuration

.NET 4.8.1 Windows Server 2016 (x64)

Other information

Only happens on some machines

Khaos66 commented 5 months ago

Two suggestions:

  1. Put preamble() in RetryHelper.TryCallAction in a try..catch, too. And ignore the exception.
  2. In Speller.OnIdle check if the thread is actually able to call COM and evade RPC_E_CANTCALLOUT_ININPUTSYNCCALL
lindexi commented 5 months ago

Reference https://stackoverflow.com/questions/54204493/wpf-spell-check-causes-exceptions-on-some-machines

Reference https://learn.microsoft.com/en-us/answers/questions/255683/system-runtime-interopservices-comexception-an-out

And the {7AB36653-1796-484B-BDFA-E74F1DB7C1DC} is the Microsoft Spell Checker Factory Class.