There are times when being able to limit the pattern matching duration of regex operations could be useful. In particular, when working with user supplied patterns to match data, the pattern might exhibit poor performance due to nested quantifiers and excessive back-tracking (see catastrophic backtracking). One way to apply a timeout is to run the regex asynchronously, but this can be tedious and clutters the code.
According to what’s new in the .NET Framework 4.5 Developer Preview it looks like there’s a new built-in approach to support this:
Ability to limit how long the regular expression engine will attempt
to resolve a regular expression before it times out.
How can I use this feature? Also, what do I need to be aware of when using it?
Note: I’m asking and answering this question since it’s encouraged.
I recently researched this topic since it interested me and will cover the main points here. The relevant MSDN documentation is available here and you can check out the
Regexclass to see the new overloaded constructors and static methods. The code samples can be run with Visual Studio 11 Developer Preview.The
Regexclass accepts aTimeSpanto specify the timeout duration. You can specify a timeout at a macro and micro level in your application, and they can be used together:"REGEX_DEFAULT_MATCH_TIMEOUT"property using theAppDomain.SetDatamethod (macro application-wide scope)matchTimeoutparameter (micro localized scope)When the
AppDomainproperty is set, allRegexoperations will use that value as the default timeout. To override the application-wide default you simply pass amatchTimeoutvalue to the regex constructor or static method. If anAppDomaindefault isn’t set, andmatchTimeoutisn’t specified, then pattern matching will not timeout (i.e., original pre-.NET 4.5 behavior).There are 2 main exceptions to handle:
RegexMatchTimeoutException: thrown when a timeout occurs.ArgumentOutOfRangeException: thrown when “matchTimeoutis negative or greater than approximately 24 days.” In addition, aTimeSpanvalue of zero will cause this to be thrown.Despite negative values not being allowed, there’s one exception: a value of -1 ms is accepted. Internally the
Regexclass accepts -1 ms, which is the value of theRegex.InfiniteMatchTimeoutfield, to indicate that a match should not timeout (i.e., original pre-.NET 4.5 behavior).Using the matchTimeout parameter
In the following example I’ll demonstrate both valid and invalid timeout scenarios and how to handle them:
When using an instance of the
Regexclass you have access to theMatchTimeoutproperty:Using the AppDomain property
The
"REGEX_DEFAULT_MATCH_TIMEOUT"property is used set an application-wide default:If this property is set to an invalid
TimeSpanvalue or an invalid object, aTypeInitializationExceptionwill be thrown when attempting to use a regex.Example with a valid property value:
Using the above example with an invalid (negative) value would cause the exception to be thrown. The code that handles it writes the following message to the console:
In both examples the
ArgumentOutOfRangeExceptionisn’t thrown. For completeness the code shows all the exceptions you can handle when working with the new .NET 4.5Regextimeout feature.Overriding AppDomain default
Overriding the
AppDomaindefault is done by specifying amatchTimeoutvalue. In the next example the match times out in 2 seconds instead of the default of 5 seconds.Closing Remarks
MSDN recommends setting a time-out value in all regular expression pattern-matching operations. However, they don’t draw your attention to issues to be aware of when doing so. I don’t recommend setting an AppDomain default and calling it a day. You need to know your input and know your patterns. If the input is large, or the pattern is complex, an appropriate timeout value should be used. This might also entail measuring your critically performing regex usages to assign sane defaults. Arbitrarily assigning a timeout value to a regex that used to work fine may cause it to break if the value isn’t long enough. Measure existing usages before assigning a value if you think it might abort the matching attempt too early.
Moreover, this feature is useful when handling user supplied patterns. Yet, learning how to write proper patterns that perform well is important. Slapping a timeout on it to make up for a lack of knowledge in proper pattern construction isn’t good practice.