场景与需求

需要执行一段第三方的代码,这段代码可能死锁/卡死/死循环,在超时之后,如果没有结束,则认为任务执行失败,退出执行。

实现方案1:使用 Task 超时

实现方法参考:

https://www.cnblogs.com/jasongrass/p/10354727.html

但这里有一个问题,既然被执行的任务可能死锁,即可能永远不会结束(除非进程退出),如果使用上述方式,将有一个线程始终被占用,无法释放,这是很浪费资源的。

实现方案2:使用 Thread

基本思路:

执行任务,超时则将任务所在 Thread 终止(Abord)。

基本代码(还有需要完善,如支持返回值等。)

using System;
using System.Threading;
using System.Threading.Task; public class ForceCancellationAction
{
private CancellationTokenSource CancellationTokenSource { get; } private readonly Action _action;
private readonly TimeSpan _timeout; public Exception BusinessException { get; private set; } public bool IsFinishedCauseTimeout { get; private set; } public ForceCancellationAction(Action action, TimeSpan timeout)
{
_action = action;
_timeout = timeout;
CancellationTokenSource = new CancellationTokenSource();
} /// <summary>
/// 执行指定的任务,如果任务执行超时,任务将被强制终止。
/// </summary>
/// <returns></returns>
public Task Do()
{
Thread thread = new Thread(TargetThreadAction)
{
IsBackground = true
}; return Task.Run(async () =>
{
try
{
thread.Start();
try
{
await Task.Delay(_timeout, CancellationTokenSource.Token); // 计时到,强制终止目标线程
thread.Abort();
}
catch (TaskCanceledException)
{
// 目标线程中的工作正确结束
}
}
catch (Exception ex)
{
Log.Error("[ForceCancellationAction]", ex);
} });
} private void TargetThreadAction()
{
try
{
_action();
}
catch (ThreadAbortException)
{
// 计时到,线程被强制终止。
IsFinishedCauseTimeout = true; // ThreadAbortException 会被重新抛出,所以,需要调用 Thread.ResetAbort(); 重启线程。
// [ThreadAbortException Class (System.Threading) | Microsoft Docs](https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.threadabortexception?view=netframework-4.8 )
Thread.ResetAbort();
}
catch (Exception ex)
{
Log.Error("[ForceCancellationAction]", ex); // 目标执行代码抛了业务异常
BusinessException = ex;
}
finally
{
// 目标线程执行完毕,取消等待计时。
CancellationTokenSource.Cancel();
}
}
}

具体调用:

var forceAction = new ForceCancellationAction(() =>
{
// 可能死锁/卡死/死循环的代码
}, TimeSpan.FromSeconds(2));
await forceAction.Do();

这样,在被执行任务出现意外卡死时,可以强制杀死线程。

注意点

需要注意的是,ThreadAbortException 捕获后,需要恢复线程,让其“自然”结束,因为这个异常是接不住的,会一直向上抛出,除非恢复线程。

参考:

ThreadAbortException Class (System.Threading) | Microsoft Docs

原文链接:

https://www.cnblogs.com/jasongrass/p/11252352.html

最新文章

  1. Javascript9张思维导图
  2. 转载: 查看HADOOP中一个文件有多少块组成及所在机器ip
  3. NYOJ 1058 部分和问题
  4. 浏览器的中的 XMLHttpRequest 对象的使用
  5. MyEclipse 10 和 2014 两个版本共存破解 - imsoft.cnblogs
  6. lightoj 1019
  7. C++ 引用(&amp;)
  8. BZOJ2134: 单选错位
  9. ListView属性解释
  10. NodeJS常用模块介绍
  11. hdu_1950_Bridging signals(LIS)
  12. WebApi 的CRUD 的方法的应用
  13. vs2012建一个空解决方案添加以前老版本的Web项目调试弹出window安全
  14. Firefox driver 那些事~
  15. UOJ#185. 【ZJOI2016】小星星 容斥原理 动态规划
  16. BZOJ1064 NOI2008 假面舞会 图论
  17. 逆向知识之CS辅助/外挂专题.2.实现CS1.6透视原理
  18. Windsor
  19. Haskell(一 )------ Windos下环境配置
  20. Java Web c3p0 pool池泄漏优化与日志分析

热门文章

  1. linux下 sort | uniq | wc | less 几个命令的基本用法
  2. 【面试突击】-RabbitMQ常见面试题(三)
  3. xcode 运行出现的相应配置问题以及解决办法
  4. 禁止ViewPager滑动
  5. 记录TortoiseGit=&gt;https请求/ssh请求配置
  6. hisi mmz模块驱动讲解
  7. java链接集合
  8. Ubuntu 18.04安装 pyenv、pyenv-virtualenv、virtualenv、Numpy、SciPy、Pillow、Matplotlib
  9. CentOS离线安装Rust
  10. 浅谈字符串Hash