Thread 另类用法,如何执行一段可能死锁/卡死/死循环的代码
场景与需求
需要执行一段第三方的代码,这段代码可能死锁/卡死/死循环,在超时之后,如果没有结束,则认为任务执行失败,退出执行。
实现方案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
Thread 另类用法,如何执行一段可能死锁/卡死/死循环的代码的更多相关文章
- 研究 Javascript的&&和||的另类用法
这篇文章主要介绍了Javascript的&&和||的另类用法,需要的朋友可以参考下 最近也没什么心思写文章了,感觉总有忙不完的事情,呵. 不过这些天又开始研究起 Titanium 来, ...
- Javascript的&&和||的另类用法
Javascript的&&和||的另类用法. 又开始研究起 Titanium 来,发现其官方出品的MVC框架(Alloy)还是挺不错的,刚开始苦于没有好的代码来学习,文档又少,所以一直 ...
- C#实现不影响当前线程情况下间隔一定的时间执行一段代码
大家知道C#间隔一定时间去执行一段代码,常用的有 1. Thread.Sleep(多少毫秒); 2. 使用Timer控件间隔一定的时间,设置执行一次 以上两种方法,实现起来不难,弊端在于会阻塞当前线程 ...
- Python装饰器的另类用法
之前有比较系统介绍过Python的装饰器(请查阅<详解Python装饰器>),本文算是一个补充.今天我们一起探讨一下装饰器的另类用法. 语法回顾 开始之前我们再将Python装饰器的语法回 ...
- 写在Github被微软收购之际 - Github的那些另类用法
这几天朋友圈被微软75亿美元收购Github的新闻刷屏了.Jerry也来贡献一篇和Github相关的文章. 这篇文章包含了Jerry平时对于Github的一些另类用法.目录如下: 1. 部署HTML应 ...
- Rpm另类用法加固Linux安全
Rpm另类用法加固Linux安全 RPM是Red Hat Package Manager的缩写即Red Hat软件管理器.它是一个开放的包管理软件,由Red Hat公司所开发和维护,可以在Red ...
- 关于ScheduledExecutorService执行一段时间之后就不执行的问题
在项目中使用java的定时任务时,有的时候执行一段时间后没任何反应了.这里有篇文章说了这个问题.猛击下面的链接. http://blog.163.com/scuqifuguang@126/blog/s ...
- Unity 延迟执行一段代码的较为优雅的方式
在Unity中,延时执行一段代码或者一个方法或者几个方法的情况非常普遍. 一般会用到Invoke和InvokeRepeating方法.顾名思义,第一个是执行一次,第二个是重复执行. 看下定义: voi ...
- [转]Unity 延迟执行一段代码的较为优雅的方式
Unity中,延时执行一段代码或者一个方法或者几个方法的情况非常普遍. 一般会用到Invoke和InvokeRepeating方法.顾名思义,第一个是执行一次,第二个是重复执行. 看下定义: void ...
随机推荐
- django实现客户端文件下载
基于django项目,由于不是专门讲文件的下载,这里仅是项目需要,所以可能不是特别的详细.仅做流程的演示: 实现过程: 1.准备下载url # 下载文件 url(r'^download_file/$' ...
- Python【day 14-3】二分法查找
#二分法查找 #方法1 循环+左右边界变动,两者差减半 #方法2 递归+新列表长度减半 #方法3 递归+左右边界变动,两者差减半 #方法1 循环+左右边界变动,两者差减半 def recursion1 ...
- JS原生对象实现异步请求以及JQ的ajax请求四种方式
一.JS原生方式异步请求 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="A ...
- Typescript基础(1)——数据类型
前言 这是开始学习Typescript的一些笔记,涉及的都是很基础的知识点.大神们请绕路或者欢迎指点.今天开始第一部分数据类型的学习. 数据类型 Typescript中为了使代码编写更加规范,更加易于 ...
- xml的解析(概述)
使用java解析xml☆☆☆ 四个类:分别是针对dom和sax解析使用的类 -dom : DocumentBuilder:解析器类 -这个类是个抽象类,不能new, ...
- JavaScript初探 四 (程序结构)
JavaScript 结构 JavaScript 程序结构 JavaScript支持几乎和C语言一样的程序结构 分支结构 循环结构 分支结构 条件分支 if-else if语句:判断条件为true则执 ...
- linux用户管理章节笔记
1 更改有效用户组 :newgrp zeng 把当前用户的有效用户组更改为zeng.事后可以使用groups命令查看. 2 在使用useradd命令增加用户时,在/etc/passwd的值一般会参考 ...
- windows双网卡绑定
windows双网卡绑定 开门贱山: 以下内容纯属抄袭,如有雷同,也是醉了~~!! ————————————— ...
- 【cf343】D. Water Tree(dfs序+线段树)
传送门 题意: 给出一个以\(1\)为根的有根树,起始每个结点都为\(0\),现在有三种操作: 1.将\(v\)及\(v\)的子树都置为\(1\): 2.将\(v\)及其所有的祖先都置为\(0\): ...
- 用java写爬虫
今天学了怎么用java代码获取要爬取页面的源代码,因为只写了一点,所以接下来会陆续跟新此文章 首先,看一下我写的代码 这就是爬取下来的网页源代码,第一张图刚刚补注释有个注释写错了,别误导你们就行,接下 ...