场景与需求

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

实现方案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 另类用法,如何执行一段可能死锁/卡死/死循环的代码的更多相关文章

  1. 研究 Javascript的&&和||的另类用法

    这篇文章主要介绍了Javascript的&&和||的另类用法,需要的朋友可以参考下 最近也没什么心思写文章了,感觉总有忙不完的事情,呵. 不过这些天又开始研究起 Titanium 来, ...

  2. Javascript的&&和||的另类用法

    Javascript的&&和||的另类用法. 又开始研究起 Titanium 来,发现其官方出品的MVC框架(Alloy)还是挺不错的,刚开始苦于没有好的代码来学习,文档又少,所以一直 ...

  3. C#实现不影响当前线程情况下间隔一定的时间执行一段代码

    大家知道C#间隔一定时间去执行一段代码,常用的有 1. Thread.Sleep(多少毫秒); 2. 使用Timer控件间隔一定的时间,设置执行一次 以上两种方法,实现起来不难,弊端在于会阻塞当前线程 ...

  4. Python装饰器的另类用法

    之前有比较系统介绍过Python的装饰器(请查阅<详解Python装饰器>),本文算是一个补充.今天我们一起探讨一下装饰器的另类用法. 语法回顾 开始之前我们再将Python装饰器的语法回 ...

  5. 写在Github被微软收购之际 - Github的那些另类用法

    这几天朋友圈被微软75亿美元收购Github的新闻刷屏了.Jerry也来贡献一篇和Github相关的文章. 这篇文章包含了Jerry平时对于Github的一些另类用法.目录如下: 1. 部署HTML应 ...

  6. Rpm另类用法加固Linux安全

    Rpm另类用法加固Linux安全   RPM是Red Hat Package Manager的缩写即Red Hat软件管理器.它是一个开放的包管理软件,由Red Hat公司所开发和维护,可以在Red ...

  7. 关于ScheduledExecutorService执行一段时间之后就不执行的问题

    在项目中使用java的定时任务时,有的时候执行一段时间后没任何反应了.这里有篇文章说了这个问题.猛击下面的链接. http://blog.163.com/scuqifuguang@126/blog/s ...

  8. Unity 延迟执行一段代码的较为优雅的方式

    在Unity中,延时执行一段代码或者一个方法或者几个方法的情况非常普遍. 一般会用到Invoke和InvokeRepeating方法.顾名思义,第一个是执行一次,第二个是重复执行. 看下定义: voi ...

  9. [转]Unity 延迟执行一段代码的较为优雅的方式

    Unity中,延时执行一段代码或者一个方法或者几个方法的情况非常普遍. 一般会用到Invoke和InvokeRepeating方法.顾名思义,第一个是执行一次,第二个是重复执行. 看下定义: void ...

随机推荐

  1. 易优CMS:foreach的基础用法

      [基础用法] 名称:foreach 功能:数据/记录循环输出标签(注:类似与volist标签,只是更加简单,没有太多额外的属性.) 语法: {eyou:channel type='top'} {e ...

  2. JS中new操作符源码实现

    首先我们来看一下实例化一个对象做了浏览器做了什么事情 new的四步操作: 1. 创建一个空对象 2. 设置空对象的__proto__属性继承构造函数的prototype属性,也就是继承构造函数的原型对 ...

  3. CSTC-2017-Web-writeup

    0x01  前言 这一次的比赛web题只做出来3个,也是菜的抠脚.. 0x02 web-签到题   php弱类型 查看源码,发现是代码审计,要求用户名必须为字母,密码必须为数字,登陆页面可以用开头为0 ...

  4. 强大的Charles的使用,强大的flutter1.9

    <a href="http://www.cocoachina.com/articles/37551?filter=ios"> 强大的Charles 强大的flutter

  5. 【XML】XPath表达式

    XPath简介 XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言. XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力.起 ...

  6. linux下查看程序占用多少内存

    执行 ps auxVSZ(或VSS)列 表示,程序占用了多少虚拟内存:RSS列 表示, 程序占用了多少物理内存:虚拟内存可以不用考虑,它并不占用实际物理内存. 或执行top 命令 VIRT(或VSS) ...

  7. golang数据结构和算法之BinarySearch二分查找法

    基础语法差不多了, 就需要系统的撸一下数据结构和算法了. 没找到合适的书, 就参考github项目: https://github.com/floyernick/Data-Structures-and ...

  8. c# WF 第8节 label控件

    本节内容: 1: 文本控件 2:实现label的你追我赶实例 1:文本控件 2:实现label的你追我赶实例 步骤1 : 步骤2 : 知识点:

  9. c# 第29节 类

    本节内容: 1:类是什么 2:声明类 3:类的使用 1:类是什么 2:声明类 在生产上的声明:如下操作   或者快捷操作 ctrl+shift+a 键 出现如下界面: 3:类的使用 using Sys ...

  10. 各版本mysql修改root密码

    今天在安装mysql5.7.8的时候遇到一些问题,首当其冲便的是初始root密码的变更,特分享解决方法如下: 1.mysql5.7会生成一个初始化密码,而在之前的版本首次登陆不需要登录. shell& ...