使用文本框和自定义词典进行拼写会降低我在C#WPF中的应用程序速度

时间:2020-12-14 00:57:03

I am using a WPF TextBoxes inside my WinForm application for spell checking. Each time I create one, I load the same file in as a CustomDictionary. All has been fine until recently. Now, they take a long time to load, up to a second. Some forms have 30 or more, meaning delays of nearly half a minute. This seems to be the case Windows 10 (not Windows 8 as I originally posted). The application is running under DotNet 4.0, I have tried 4.5 and 4.6 (not 4.61) and all versions are slow.

我在WinForm应用程序中使用WPF TextBoxes进行拼写检查。每次创建一个,我都将相同的文件作为CustomDictionary加载。一切都很好,直到最近。现在,它们需要很长时间才能加载,最多一秒钟。有些表格有30个或更多,意味着延迟近半分钟。这似乎是Windows 10(不是我最初发布的Windows 8)的情况。应用程序在DotNet 4.0下运行,我尝试过4.5和4.6(不是4.61),所有版本都很慢。

I have seen sfaust’s question Spell check textbox in Win10 - Slow and am7zd’s answer. Thanks to these, I looked at the GLOBAL registry key in HKEY_CURRENT_USER\Software\Microsoft\Spelling\Dictionaries. I have 580 entries (after pruning out entries without matching files) and still things are slow.

我已经看到了sfaust的问题在Win10中拼写检查文本框 - 慢和am7zd的答案。多亏了这些,我查看了HKEY_CURRENT_USER \ Software \ Microsoft \ Spelling \ Dictionaries中的GLOBAL注册表项。我有580个条目(修剪掉没有匹配文件的条目)但仍然很慢。

At present, every time I create a TextBox and add a custom dictionary to it, a new entry seems to be generated in _GLOBAL_

目前,每次创建TextBox并向其添加自定义词典时,似乎都会在_GLOBAL_中生成一个新条目

  • Is there a better way of doing things than loading the custom dictionary in from file every time?
  • 有没有比每次从文件加载自定义词典更好的做事方式?
  • Is there a way of re-using the same entry in _GLOBAL_ every time instead of creating a new one?
  • 有没有办法在每次重复使用_GLOBAL_中的相同条目而不是创建一个新条目?
  • Is there a clean way of clearing previous entries in GLOBAL created by my application and their matching .dic files when closing the application (or on restarting it)?
  • 在关闭应用程序(或重新启动它)时,是否有一种清除方式来清除我的应用程序创建的GLOBAL中的先前条目及其匹配的.dic文件?
  • I could clear _GLOBAL_ completely each time I start my application. This brings back the speed I want, but what is the downside?
  • 每次启动应用程序时,我都可以完全清除_GLOBAL_。这带回了我想要的速度,但缺点是什么?

Any advice gratefully received.

任何建议都感激不尽。

1 个解决方案

#1


4  

No answers from anyone else, so this is what I have done:

没有其他人的答案,所以这就是我所做的:

  1. I made sure I use CustomDictionaries.Remove on all textboxes with custom dictionaries before closing the form they are on. This gets rid of new entries in _GLOBAL_ and the related files in AppData\Local\Temp.
  2. 我确保在关闭它们所在的表单之前,在所有带有自定义词典的文本框上使用CustomDictionaries.Remove。这消除了_GLOBAL_中的新条目以及AppData \ Local \ Temp中的相关文件。

But there will be times when things go wrong or the user just ends the task, leaving _GLOBAL_ entries and .dic files in place, so:

但有时会出现问题或用户刚刚结束任务,留下_GLOBAL_条目和.dic文件,所以:

  1. I decided to take things a stage further. When I start my application, I will not only clean entries in _GLOBAL_ that don't have matching files (as suggested in the previous post referenced above), but also to remove all entries referring to .dic files in AppData\Local\Temp. My theory being that anyone who has left entries there didn't mean to, otherwise they would probably have saved the .dic file in a different folder (as Microsoft Office does).

    我决定进一步采取行动。当我启动我的应用程序时,我不仅会清除_GLOBAL_中没有匹配文件的条目(如上面引用的上一篇文章中所述),还要删除引用AppData \ Local \ Temp中.dic文件的所有条目。我的理论是,任何在那里留下条目的人都不是故意的,否则他们可能会将.dic文件保存在不同的文件夹中(就像Microsoft Office那样)。

        try
        {
    
            string[] allDictionaries = (string[])Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Spelling\Dictionaries", "_Global_",  new string[0]);
    
            if (allDictionaries.Count() > 0)
            {
                List<string> realDictionaries = new List<string>();
                bool changedSomething = false;
    
                foreach (string thisD in allDictionaries)
                {
                    if (File.Exists(thisD))
                    {
                        if (thisD.Contains(@"\AppData\Local\Temp\"))
                        {
                            // Assuming that anyone who wants to keep a permanent .dic file will not store it in \AppData\Local\Temp
                            // So delete the file and don't copy the name of the dictionary into the list of good dictionaries.
                            File.Delete(thisD);
                            changedSomething = true;
                        }
                        else
                        {
                            realDictionaries.Add(thisD);
                        }
                    }
                    else
                    {
                        // File does not exist, so don't copy the name of the dictionary into the list of good dictionaries.
                        changedSomething = true;
                    }
                }
    
                if (changedSomething)
                {
                    Registry.SetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Spelling\Dictionaries", "_Global_", realDictionaries.ToArray());
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(this, "Error clearing up old dictionary files.\n\nFull message:\n\n" + ex.Message, "Unable to delete file", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    

I am still wondering if it is totally safe to clear entries in _GLOBAL_ that refer to files in AppData\Local\Temp. Surely people shouldn't be leaving important stuff in a temp folder... should they?

我仍然想知道清除_GLOBAL_中引用AppData \ Local \ Temp中文件的条目是否完全安全。当然人们不应该把重要的东西放在临时文件夹中......不是吗?

What would be really nice would be an overload to CustomDictionaries.Add that allows us to set the name and folder of the .dic file, allowing all the textboxes in the same application to share the same .dic file and making sure we don't leave a load of redundant entries and files with seemingly random names hanging around in the first place..... please Microsoft.

什么是真正好的将是CustomDictionaries.Add的重载,它允许我们设置.dic文件的名称和文件夹,允许同一个应用程序中的所有文本框共享相同的.dic文件,并确保我们不留下一堆冗余的条目和文件,看起来随机的名字在第一位徘徊.....请微软。

#1


4  

No answers from anyone else, so this is what I have done:

没有其他人的答案,所以这就是我所做的:

  1. I made sure I use CustomDictionaries.Remove on all textboxes with custom dictionaries before closing the form they are on. This gets rid of new entries in _GLOBAL_ and the related files in AppData\Local\Temp.
  2. 我确保在关闭它们所在的表单之前,在所有带有自定义词典的文本框上使用CustomDictionaries.Remove。这消除了_GLOBAL_中的新条目以及AppData \ Local \ Temp中的相关文件。

But there will be times when things go wrong or the user just ends the task, leaving _GLOBAL_ entries and .dic files in place, so:

但有时会出现问题或用户刚刚结束任务,留下_GLOBAL_条目和.dic文件,所以:

  1. I decided to take things a stage further. When I start my application, I will not only clean entries in _GLOBAL_ that don't have matching files (as suggested in the previous post referenced above), but also to remove all entries referring to .dic files in AppData\Local\Temp. My theory being that anyone who has left entries there didn't mean to, otherwise they would probably have saved the .dic file in a different folder (as Microsoft Office does).

    我决定进一步采取行动。当我启动我的应用程序时,我不仅会清除_GLOBAL_中没有匹配文件的条目(如上面引用的上一篇文章中所述),还要删除引用AppData \ Local \ Temp中.dic文件的所有条目。我的理论是,任何在那里留下条目的人都不是故意的,否则他们可能会将.dic文件保存在不同的文件夹中(就像Microsoft Office那样)。

        try
        {
    
            string[] allDictionaries = (string[])Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Spelling\Dictionaries", "_Global_",  new string[0]);
    
            if (allDictionaries.Count() > 0)
            {
                List<string> realDictionaries = new List<string>();
                bool changedSomething = false;
    
                foreach (string thisD in allDictionaries)
                {
                    if (File.Exists(thisD))
                    {
                        if (thisD.Contains(@"\AppData\Local\Temp\"))
                        {
                            // Assuming that anyone who wants to keep a permanent .dic file will not store it in \AppData\Local\Temp
                            // So delete the file and don't copy the name of the dictionary into the list of good dictionaries.
                            File.Delete(thisD);
                            changedSomething = true;
                        }
                        else
                        {
                            realDictionaries.Add(thisD);
                        }
                    }
                    else
                    {
                        // File does not exist, so don't copy the name of the dictionary into the list of good dictionaries.
                        changedSomething = true;
                    }
                }
    
                if (changedSomething)
                {
                    Registry.SetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Spelling\Dictionaries", "_Global_", realDictionaries.ToArray());
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(this, "Error clearing up old dictionary files.\n\nFull message:\n\n" + ex.Message, "Unable to delete file", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    

I am still wondering if it is totally safe to clear entries in _GLOBAL_ that refer to files in AppData\Local\Temp. Surely people shouldn't be leaving important stuff in a temp folder... should they?

我仍然想知道清除_GLOBAL_中引用AppData \ Local \ Temp中文件的条目是否完全安全。当然人们不应该把重要的东西放在临时文件夹中......不是吗?

What would be really nice would be an overload to CustomDictionaries.Add that allows us to set the name and folder of the .dic file, allowing all the textboxes in the same application to share the same .dic file and making sure we don't leave a load of redundant entries and files with seemingly random names hanging around in the first place..... please Microsoft.

什么是真正好的将是CustomDictionaries.Add的重载,它允许我们设置.dic文件的名称和文件夹,允许同一个应用程序中的所有文本框共享相同的.dic文件,并确保我们不留下一堆冗余的条目和文件,看起来随机的名字在第一位徘徊.....请微软。