Thread.Abort() 并在 finally 之后延迟
Posted
技术标签:
【中文标题】Thread.Abort() 并在 finally 之后延迟【英文标题】:Thread.Abort() and delay after finally 【发布时间】:2014-10-22 22:14:45 【问题描述】:当调用 Thread.Abort() 并且该线程正在执行 finally 块时,线程不会中止,直到 finally 块完成。但是,正如我所见,ThreadAbortException 不是在 finally 块结束之后生成的,而是在一些延迟之后生成的:
private static volatile int val1 = 0;
public static void Func1()
try
finally
Thread.Sleep(5000);
//Func2();
while (true)
val1++;
public static void Main()
var thread = new Thread(Func1);
thread.Start();
Thread.Sleep(1000);
thread.Abort();
thread.Join();
Console.WriteLine(val1); // val1 is non-zero!
在此示例中,Main() 末尾的 val1 将非零。为什么会这样?
如果我取消注释对 Func2() 的调用(Func2 是任何方法,可能为空),val1 的输出将显示“0”。为什么添加方法会影响线程中止点?
【问题讨论】:
有趣的问题,但是在没有附加调试器的发布模式下,我可以得到一个非零数字val1
也 Func2()
未注释的空函数。在发布时附加调试器或在没有调试器的情况下调试时都给我 0。
Thread.Abort
很糟糕,非常很糟糕。它将使您的应用程序处于不可预测的状态,并且您在使用后将无法依赖关于程序行为的常见假设。你应该avoid不惜一切代价打电话给它。
【参考方案1】:
在这种情况下,用lock
包围增量可能很有用。锁控制对该成员的访问。 Abort
方法只是通知线程“嘿,你现在可以停止”,但它不会杀死线程。所以线程可以在Abort
之后存活片刻。访问lock
线程检查它是否被中止并在需要时自行杀死它。
这是您编辑的示例代码
using System;
using System.Threading;
namespace ConsoleApp1
class Program
private static volatile int val1 = 0;
static Object Locker = new Object();
public static void Func1()
try
finally
Thread.Sleep(5000);
//Func2();
while (true)
//Lock the access to the member
lock (Locker)
val1++;
public static void Main()
var thread = new Thread(Func1);
thread.Start();
Thread.Sleep(1000);
//Not needed. Just to make sure
lock (Locker)
thread.Abort();
thread.Join();
Console.WriteLine(val1); // val1 is non-zero!
// Now it is zero
Console.ReadLine();
抱歉回复晚了
【讨论】:
Thread.Abort
可以中止锁定区域中间的线程。如果发生这种情况,它不会释放锁。这是非常危险的建议。
它将释放锁,导致锁的释放是在 finally 块内部的,如果线程在 finally 的一种情况下中止,finally 块将始终执行,因为线程实际上被杀死了一个线程中止异常。您也可以只处理该异常。检查this
这并不总是正确的。如果线程在finally 块期间 中止,它可以跳过释放锁。请参阅 here 的讨论,其中有一些实际设计 C# 和 .NET 的人。以上是关于Thread.Abort() 并在 finally 之后延迟的主要内容,如果未能解决你的问题,请参考以下文章
可以像中止一个Thread(Thread.Abort方法)一样中止一个Task吗?