Controlling the timeout in regular expressions

.NET 4.5 gives us improved control on the resolution of regular expressions so we can react when they don't resolve on time. This is extremely useful if we don't control the regular expressions/patterns, such as the ones provided by the users.

A badly formed pattern can have bad performance due to excessive backtracking and this new feature is really a lifesaver.

How to do it...

Next we are going to control the timeout in the regular expression, where we will react if the operation takes more than 1 millisecond:

  1. Create a new Visual Studio project of type Console Application, named caRegexTimeout.
  2. Open the Program.cs file and add a using clause for using regular expressions:
    Using System.Text.RegularExpressions;
  3. Add the following method and call it from the Main function:
    private static void ExecuteRegexExpression() {
    bool RegExIsMatch = false;
    string testString = "One Tile to rule them all, One Tile to find them… ";
    string RegExPattern = @"([a-z ]+)*!";
    TimeSpantsRegexTimeout = TimeSpan.FromMilliseconds(1);
    
    try
        {
    RegExIsMatch = Regex.IsMatch(testString, RegExPattern, RegexOptions.None, tsRegexTimeout);
        }
    catch (RegexMatchTimeoutException ex)
        {
    Console.WriteLine("Timeout!!");
    Console.WriteLine("- Timeout specified: " + ex.MatchTimeout);
        }
    catch (ArgumentOutOfRangeException ex)
        {
    Console.WriteLine("ArgumentOutOfRangeException!!");
    Console.WriteLine(ex.Message);
        }
    Console.WriteLine("Finished succesfully: " + RegExIsMatch.ToString());
    Console.ReadLine();
    }
  4. If we execute it, we will see that it doesn't finish successfully, showing us some details in the console window.
    How to do it...
  5. Next, we will change testString and RegExPattern to:
    String testString = "[email protected]";
    String RegExPattern = @"^([w-.]+)@([w-.]+).[a-zA-Z]{2,4}$";
  6. If we run it, we will now see that it runs and finishes successfully.

How it works...

The RegEx.IsMatch() method now accepts a parameter, which is matchTimeout of type TimeSpan, indicating the maximum time that we allow for the matching operation. If the execution time exceeds this amount, RegexMatchTimeoutException is launched.

In our code, we have captured it with a try-catch statement to provide a custom message and of course to react upon a badly formed regex pattern taking too much time.

We have tested it with an expression that will take some more time to validate and we got the timeout. When we changed the expression to a good one with a better execution time, the timeout was not reached.

Additionally, we also watched out for the ArgumentOutOfRangeException, which is thrown when TimeSpan is zero, or negative, or greater than 24 days.

There'smore...

We could also set a global matchTimeout for the application through the "REGEX_DEFAULT_MATCH_TIMEOUT" property with the AppDomain .SetData method:

AppDomain.CurrentDomain.SetData("REGEX_DEFAULT_MATCH_TIMEOUT",TimeSpan.FromMilliseconds(200));

Anyway, if we specify the matchTimeout parameter, we will override the global value.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset