Thread 另类用法,如何执行一段可能死锁/卡死/死循环的代码
2024-09-03 03:41:36
场景与需求
需要执行一段第三方的代码,这段代码可能死锁/卡死/死循环,在超时之后,如果没有结束,则认为任务执行失败,退出执行。
实现方案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
最新文章
- Javascript9张思维导图
- 转载: 查看HADOOP中一个文件有多少块组成及所在机器ip
- NYOJ 1058 部分和问题
- 浏览器的中的 XMLHttpRequest 对象的使用
- MyEclipse 10 和 2014 两个版本共存破解 - imsoft.cnblogs
- lightoj 1019
- C++ 引用(&;)
- BZOJ2134: 单选错位
- ListView属性解释
- NodeJS常用模块介绍
- hdu_1950_Bridging signals(LIS)
- WebApi 的CRUD 的方法的应用
- vs2012建一个空解决方案添加以前老版本的Web项目调试弹出window安全
- Firefox driver 那些事~
- UOJ#185. 【ZJOI2016】小星星 容斥原理 动态规划
- BZOJ1064 NOI2008 假面舞会 图论
- 逆向知识之CS辅助/外挂专题.2.实现CS1.6透视原理
- Windsor
- Haskell(一 )------ Windos下环境配置
- Java Web c3p0 pool池泄漏优化与日志分析
热门文章
- linux下 sort | uniq | wc | less 几个命令的基本用法
- 【面试突击】-RabbitMQ常见面试题(三)
- xcode 运行出现的相应配置问题以及解决办法
- 禁止ViewPager滑动
- 记录TortoiseGit=>;https请求/ssh请求配置
- hisi mmz模块驱动讲解
- java链接集合
- Ubuntu 18.04安装 pyenv、pyenv-virtualenv、virtualenv、Numpy、SciPy、Pillow、Matplotlib
- CentOS离线安装Rust
- 浅谈字符串Hash