如何在源代码编译的Regex中指定超时值?
为源代码生成的Regex添加超时机制
你可以通过两种方式为源代码生成的Regex添加超时:
1. 在GeneratedRegex属性中预设超时(.NET 7及以上)
直接在GeneratedRegex属性里指定Timeout参数,生成的Regex实例会默认使用该超时值,后续调用Match时无需额外传参:
[GeneratedRegex(@"^[0-9A-Z]([-.\w]*[0-9A-Z])*$", RegexOptions.IgnoreCase, Timeout = "00:00:00.100")] private static partial Regex Pattern(); private static readonly Regex SCPattern = Pattern();
此时调用SCPattern.Match(input)会自动应用100毫秒的超时,超时后会抛出RegexMatchTimeoutException。
2. 使用带超时参数的Match重载
不管.NET版本,都可以直接调用Regex.Match的重载方法,显式传入超时值:
Match m = SCPattern.Match(input, 0, TimeSpan.FromMilliseconds(100));
这里第二个参数0表示从输入字符串的起始位置开始匹配,你可以根据需求调整。
修改后的最小可复现代码示例
using System.Diagnostics; using System.Text.RegularExpressions; public partial class Program { // 方法1:在属性中预设超时 [GeneratedRegex(@"^[0-9A-Z]([-.\w]*[0-9A-Z])*$", RegexOptions.IgnoreCase, Timeout = "00:00:00.100")] private static partial Regex PatternWithTimeout(); private static readonly Regex SCPatternWithTimeout = PatternWithTimeout(); // 方法2:使用默认生成,调用时传超时 [GeneratedRegex(@"^[0-9A-Z]([-.\w]*[0-9A-Z])*$", RegexOptions.IgnoreCase)] private static partial Regex Pattern(); private static readonly Regex SCPattern = Pattern(); public static void Main() { Stopwatch sw; string[] addresses = { "AAAAAAAAAAAAaaaaaaaaaaaa!@contoso.com" }; string input; foreach (var address in addresses) { string mailBox = address[..address.IndexOf('@')]; int index = 0; // 测试预设超时的源代码生成Regex index = 0; Console.WriteLine("source-compiled regex with preset timeout:"); for (int ctr = mailBox.Length - 1; ctr >= 0; ctr--) { index++; input = mailBox.Substring(ctr, index); sw = Stopwatch.StartNew(); try { Match m = SCPatternWithTimeout.Match(input); sw.Stop(); if (m.Success) Console.WriteLine("{0,2}. Matched '{1,27}' in {2}", index, m.Value, sw.Elapsed); else Console.WriteLine("{0,2}. Failed '{1,27}' in {2}", index, input, sw.Elapsed); } catch (RegexMatchTimeoutException) { sw.Stop(); Console.WriteLine("{0,2}. Timeout '{1,27}' in {2}", index, input, sw.Elapsed); } } Console.WriteLine(); // 测试调用时传超时的源代码生成Regex index = 0; Console.WriteLine("source-compiled regex with explicit timeout:"); for (int ctr = mailBox.Length - 1; ctr >= 0; ctr--) { index++; input = mailBox.Substring(ctr, index); sw = Stopwatch.StartNew(); try { Match m = SCPattern.Match(input, 0, TimeSpan.FromMilliseconds(100)); sw.Stop(); if (m.Success) Console.WriteLine("{0,2}. Matched '{1,27}' in {2}", index, m.Value, sw.Elapsed); else Console.WriteLine("{0,2}. Failed '{1,27}' in {2}", index, input, sw.Elapsed); } catch (RegexMatchTimeoutException) { sw.Stop(); Console.WriteLine("{0,2}. Timeout '{1,27}' in {2}", index, input, sw.Elapsed); } } } Console.WriteLine("Press any key ..."); Console.ReadKey(); } }
注意:处理超时场景时,需要捕获
RegexMatchTimeoutException来处理超时情况。
内容的提问来源于stack exchange,提问作者Qrt
相关产品推荐
相关产品推荐

