Win10 中的拼写检查文本框 - 慢

Spell check textbox in Win10 - Slow

我正在使用 WPF 中的内置拼写检查器。在我让用户开始升级到 windows 10 之前,它工作得很好......我认为问题在于它被用于很多小文本框。我的应用程序显示了一个网格(Telerik 的 TreeListView),其中包含我要检查拼写的列之一的文本框。我需要能够为拼写检查器提供自定义词典;我能够做到这一点的唯一方法是订阅文本框加载事件并添加如下路径:

        TextBox tb = sender as TextBox;
        tb.ContextMenu = ctx_Spell;
        IList dcts = SpellCheck.GetCustomDictionaries(tb);

        dictsList.Add(dcts);
        if (KMApplication.Settings.UserDictionary != null)
        { dcts.Add(KMApplication.Settings.UserDictionary); }

        foreach (Uri dct in KMApplication.Settings.RevitDictonaries)
        { dcts.Add(dct); }

当然,这会为每个文本框调用添加,这看起来非常浪费,但它似乎工作得很好,几乎没有明显的延迟,而且只有在加载时才会出现。但是现在 Windows 10 这似乎是一个荒谬的滞后。在我的 Windows 8.1 机器上,我加载了一个包含几千行的文件,它在大约 3 或 4 秒内出现;在我的 Windows 10 盒子上,它会在大约 10-15 分钟内出现。如果我注释掉上面代码的自定义词典部分,它在任何一台机器上都会回到大约 3-4 秒。

有谁知道更好的方法吗?或者在 Win10 中是否有解决方法?

从 .NET 4.6.1 开始(在 Win8.1 和 Win10 中),WPF 使用 OS 公开的 ISpellChecker 接口来实现其 SpellChecker,性能特征可能确实有所不同。

值得注意的是,ISpellChecker 的自定义词典注册器在全球范围内运行 - 它不再充当每个控件的注册。 (请参阅下面的知识库文章 link)。因此,为每个控件一遍又一遍地注册同一组字典是一种浪费,并且可能会降低性能。此外,OS 会在达到内部限制时开始忽略您的词典。

只需注册一次词典,或使用 http://blogs.msdn.com/b/wpf/archive/2015/10/29/wpf-in-net-4-6-1.aspx 中概述的替代注册机制并将文件放在 %appdata%\microsoft\spelling\ 下。

如果您需要在 Win7/Win8 和 Win8.1/Win10 上 运行 相同的应用程序,您可能需要检测 OS 并分支您的字典注册策略。

一般来说,自定义词典的典型使用应继续照常工作 - .NET 4.6.1 与以前的版本之间几乎没有区别。

有关其他信息,另请参阅 https://support.microsoft.com/en-us/kb/3088234

我们遇到了类似的问题,并且通过避免在加载期间在每个 TextBox 控件上重新注册自定义词典来提高性能。

不幸的是,我们在处理自定义词典的方式上遇到了另一个问题,如果您的 TextBox 控件数量很少,这也会导致加载时间非常长。

当 WPF 应用程序在 Windows 8.1/10 上的 .NET 4.6.1 中注册自定义字典时,会在 %localappdata%\Temp 中创建一个临时字典文件,并在多字符串值 _GLOBAL_ 中注册在注册表项 "Computer\HKEY_CURRENT_USER\Software\Microsoft\Spelling\Dictionaries".

如果 _GLOBAL_ 值最终引用了一个不存在的字典文件,则每当启用拼写检查的控件被初始化时,应用程序开始显示加载速度非常慢。

这可以通过使用 Visual Studio 中的 "Stop debugging" 按钮然后 运行 磁盘清理或 CCleaner 在经过足够的时间后删除临时字典文件来实现.

我们设法通过清除指向不存在的字典文件的任何链接的 _GLOBAL_ 值来解决此问题。我们的应用程序开始按预期运行。

我们提出了以下连接错误: https://connect.microsoft.com/VisualStudio/feedback/details/2153484

首先,我想提一下,我知道 post 已经有几年了,但我认为我的回答可能会帮助那些遇到同样问题但在哪里的人提出的解决方案不起作用(就像我自己)。


为我修复的是将以下代码添加到 App.config:

<runtime>
  <AppContextSwitchOverrides value="Switch.System.Windows.Controls.DoNotAugmentWordBreakingUsingSpeller=true"/>
</runtime>

或者,您也可以在 InitializeComponent() 调用后插入以下代码

AppContext.SetSwitch(@"Switch.System.Windows.Controls.DoNotAugmentWordBreakingUsingSpeller", true);

Source 1 (XAML solution)
Source 2 (C# solution)