Действительно сложная часть здесь убивали долго выполняющиеся задачи путем прохождения исполнителя нити от действий обратно на место, где она может быть прервана. Я выполнил это с помощью завернутого делегата, который передает поток, чтобы убить локальную переменную в методе, который создал лямбда.
Я представляю этот пример для вашего удовольствия. Метод, который вас действительно интересует, - CallWithTimeout.Это отменит давно работает нить на прерывании, и глотания ThreadAbortException:
Использование:
class Program
{
static void Main(string[] args)
{
//try the five second method with a 6 second timeout
CallWithTimeout(FiveSecondMethod, 6000);
//try the five second method with a 4 second timeout
//this will throw a timeout exception
CallWithTimeout(FiveSecondMethod, 4000);
}
static void FiveSecondMethod()
{
Thread.Sleep(5000);
}
статический метод делает работу:
static void CallWithTimeout(Action action, int timeoutMilliseconds)
{
Thread threadToKill = null;
Action wrappedAction =() =>
{
threadToKill = Thread.CurrentThread;
try
{
action();
}
catch(ThreadAbortException ex){
Thread.ResetAbort();// cancel hard aborting, lets to finish it nicely.
}
};
IAsyncResult result = wrappedAction.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeoutMilliseconds))
{
wrappedAction.EndInvoke(result);
}
else
{
threadToKill.Abort();
throw new TimeoutException();
}
}
}
Почему catch (ThreadAbortException)? AFAIK вы не можете поймать ThreadAbortException (он будет восстановлен после того, как останется блок catch). – csgero 2008-11-18 16:57:39
Вы, мой друг, абсолютно правы. Мы можем просто игнорировать его в этом случае и позволить потоку умереть. Пул будет пополнен, но это то, что нужно принять во внимание, если это произойдет очень часто. Это * МОЖЕТ БЫТЬ * проблема с производительностью. – TheSoftwareJedi 2008-11-18 17:06:30