在.NET 4中实现RegEx超时

平台:Silverlight 4,.NET 4

使用.NET 4.5 Developer预览版, RegEx类已得到增强,允许设置Timeout值,如果模式匹配存在问题,将阻止RegEx引擎挂起UI。

请求在.NET 4 Silverlight应用程序中实现类似function的建议。

提前致谢。

通用示例:

public static R WithTimeout(Func proc, int duration) { var wh = proc.BeginInvoke(null, null); if (wh.AsyncWaitHandle.WaitOne(duration)) { return proc.EndInvoke(wh); } throw new TimeOutException(); } 

用法:

 var r = WithTimeout(() => regex.Match(foo), 1000); 

更新:

正如Christian.K所指出的,异步线程仍将继续运行。

这是线程终止的地方:

 public static R WithTimeout(Func proc, int duration) { var reset = new AutoResetEvent(false); var r = default(R); Exception ex = null; var t = new Thread(() => { try { r = proc(); } catch (Exception e) { ex = e; } reset.Set(); }); t.Start(); // not sure if this is really needed in general while (t.ThreadState != ThreadState.Running) { Thread.Sleep(0); } if (!reset.WaitOne(duration)) { t.Abort(); throw new TimeoutException(); } if (ex != null) { throw ex; } return r; } 

更新:

修复了以上片段以正确处理exception。

它不是那么简单 – 但它可以使用两个线程完成,第一个执行正则表达式,第二个线程杀死第一个线程,如果它运行太长时间。 但这本身就存在问题。

我重新实现了上面的代码,以我认为更可靠的方式更改它。

  ///  /// Executes function proc on a separate thread respecting the given timeout value. ///  ///  /// The function to execute. /// The timeout duration. ///  public static R ExecuteWithTimeout(Func proc, TimeSpan timeout) { var r = default(R); // init default return value Exception ex = null; // records inter-thread exception // define a thread to wrap 'proc' var t = new Thread(() => { try { r = proc(); } catch (Exception e) { // this can get set to ThreadAbortException ex = e; Debug.WriteLine("Exception hit"); } }); t.Start(); // start running 'proc' thread wrapper // from docs: "The Start method does not return until the new thread has started running." if (t.Join(timeout) == false) { t.Abort(); // die evil thread! // Abort raises the ThreadAbortException int i = 0; while ((t.Join(1) == false) && (i < 20)) { // 20 ms wait possible here i++; } if (i >= 20) { // we didn't abort, might want to log this or take some other action // this can happen if you are doing something indefinitely hinky in a // finally block (cause the finally be will executed before the Abort // completes. Debug.WriteLine("Abort didn't work as expected"); } } if (ex != null) { throw ex; // oops } return r; // ah! } 

在function尚未附带的内容上获得超时的标准方法是在单独的线程上启动您想要处理的任何内容,然后在主线程中,使用具有适当超时的Thread.Join。