1

我有一个带有文本框的应用程序。用户在此框中输入文本。

我在该文本框中的 OnKeyUp 事件中触发了以下函数

private void bxItemText_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{               
    // rules is an array of regex strings
    foreach (string rule in rules)
    {
        Regex regex = new Regex(rule);
        if (regex.Match(text.Trim().ToLower()))
        {
            // matched rule is a variable
            matchedRule = rule;
            break;
        }
    }
}

我有大约 12 个字符串rules,尽管这可能会有所不同。

一旦我的文本框中的文本长度超过 80 个字符,性能就会开始下降。在 100 个字符后键入一个字母需要一秒钟才能显示出来。

我该如何优化呢?我应该在每 3 个 KeyUp 上匹配吗?我应该完全放弃 KeyUp 并每隔几秒钟自动匹配一次吗?

4

7 回答 7

4

我该如何优化呢?我应该在每 3 个 KeyUp 上匹配吗?我应该完全放弃 KeyUp 并每隔几秒钟自动匹配一次吗?

我会选择第二个选项,即放弃KeyUp并每隔几秒钟触发一次验证,或者更好的是在TextBox失去焦点时触发验证。

另一方面,我应该建议事先缓存正则表达式并编译它们,因为看起来你正在一遍又一遍地使用它们,换句话说,而不是将规则作为字符串存储在该数组中,你应该将它们存储为已编译添加或加载正则表达式对象时。

于 2013-10-15T11:22:05.260 回答
1

使用static方法调用而不是每次都创建一个新对象,static调用使用一个caching特性:优化正则表达式性能,第一部分:使用正则表达式类和正则表达式对象

这将是性能的重大改进,然后您可以提供您的正则表达式(规则)以查看是否可以在正则表达式中进行一些优化。

其他资源:

于 2013-10-15T11:56:59.160 回答
0

鉴于您似乎正在匹配关键字,您是否可以只对已编辑的文本的当前部分(即光标附近)执行匹配?设计起来可能会很棘手,尤其是对于粘贴或撤消等操作,但有很大的性能提升空间。

于 2013-10-15T13:41:54.413 回答
0

如果您需要为每个新符号确定模式,并且您关心性能,那么最终状态机似乎是最好的选择......这是更难的方法。您应该为每个符号指定允许的下一个符号的列表。如果可能的话,OnKeyUp 你只​​需进入下一个状态。您将拥有输入文本当前匹配的模式数量。我可以找到一些有用的参考资料:

FSM 示例

解释如何将正则表达式转换为 FSM 的人

正则表达式 - FSM 转换讨论

于 2013-10-15T12:51:54.697 回答
0

您不需要每次都创建一个新的正则表达式对象。如果之前使用过(自 .Net 2 起),也使用静态调用将缓存模式。这是我将如何重写它

matchedRule = Rules.FirstOrDefault( rule => Regex.IsMatch(text.Trim().ToLower(), rule));

于 2013-10-15T12:52:06.547 回答
0

在正则表达式级别将字符串组合为一个将比代码中的 foreach 更快。 将两个正则表达式合二为一

于 2013-10-15T11:41:19.477 回答
-1

预编译您的正则表达式(使用RegexOptions.Compiled)。另外,你可以通过扩展你的正则表达式来使Trim和冗余吗?ToLower您正在为每个规则运行一次TrimToLower即使您无法完全消除它们,这也是低效的

您可以尝试使您的规则互斥 - 这应该会加快速度。我做了一个简短的测试:匹配以下

“猫|汽车|出租车|盒子|气球|按钮”

可以通过这样写来加速

“ca(t|r|b)|b(ox|alloon|utton)”

于 2013-10-15T11:36:39.593 回答