Implementing RegEx Timeout in .NET 4
本文关键字:NET in Timeout RegEx Implementing | 更新日期: 2023-09-27 18:25:49
平台:Silverlight 4,.NET 4
在.NET 4.5 Developer预览版中,RegEx类得到了增强,允许设置Timeout值,以防止RegEx引擎在模式匹配出现问题时挂起UI。
请求在.NET 4 Silverlight应用程序中实现类似功能的建议。
提前谢谢。
一般示例:
public static R WithTimeout<R>(Func<R> 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<R>(Func<R> 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;
}
更新:
修复了上面的代码段以正确处理异常。
这并没有那么简单,但它可以使用两个线程来完成,第一个线程执行regex,如果itrun太长,第二个线程会杀死第一个线程。不过,这本身就有问题。
我重新实现了上面的代码,以我认为更可靠的方式对其进行了更改。
/// <summary>
/// Executes function proc on a separate thread respecting the given timeout value.
/// </summary>
/// <typeparam name="R"></typeparam>
/// <param name="proc">The function to execute.</param>
/// <param name="timeout">The timeout duration.</param>
/// <returns></returns>
public static R ExecuteWithTimeout<R>(Func<R> 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!
}
获得该功能尚未附带的超时的标准方法是,只需在一个单独的线程上启动您想要处理的任何内容,然后在主线程中使用thread.Join并设置适当的超时。