C# Thread.Abort()并在finally之后延迟

C# Thread.Abort()并在finally之后延迟,c#,multithreading,abort,finally,C#,Multithreading,Abort,Finally,当调用Thread.Abort()时,该线程正在执行finally块,那么直到finally块完成,线程才会中止。但是,正如我所看到的,ThreadAbortException不是在finally块结束之后生成的,而是在经过一些延迟之后生成的: private static volatile int val1 = 0; public static void Func1() { try { } finally { Thread.Sleep(

当调用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”。为什么添加方法会影响线程终止点?

在这种情况下,可以使用
锁将增量包围起来。锁控制该成员的访问。
Abort
方法只是通知线程“嘿,你现在可以停止了”,但它不会终止线程。因此,线程可以在
中止后保持活动状态几分钟。访问
线程检查它是否被中止,并在需要时自行终止

下面是您的示例代码

使用系统;
使用系统线程;
名称空间控制台EAPP1
{
班级计划
{
私有静态volatile int val1=0;
静态对象锁定器=新对象();
公共静态void Func1()
{
尝试
{
}
最后
{
睡眠(5000);
}
//Func2();
while(true)
{
//锁定对成员的访问权限
锁(储物柜)
val1++;
}
}
公共静态void Main()
{
变量线程=新线程(Func1);
thread.Start();
睡眠(1000);
//不需要,只是为了确定一下
锁(储物柜)
{
thread.Abort();
thread.Join();
}
Console.WriteLine(val1);//val1不是零!
//现在是零
Console.ReadLine();
}
}
}

很抱歉回答得太晚了

有趣的问题,但是在没有附加调试器的发布模式下,我可以为
val1
Func2()
获取一个非零的数字,并使用空函数取消注释。如果在发行版中附加了调试器,或者在调试中使用我们的调试器,而没有调试器,则都会给我0。
Thread.Abort
很糟糕,非常糟糕。它将使您的应用程序处于不可预测的状态,并且在使用它之后,您将无法依赖关于程序行为的常见假设。您应该不惜一切代价调用它。<代码>线程。异常终止>代码>可以在锁定区域的中间中止线程。如果发生这种情况,它将不会释放锁。这是一个非常危险的建议。它会释放锁,因为锁的释放在finally块中是内部的,如果线程在finally的某个情况下中止,finally块将始终执行,因为线程实际上会因为ThreadAbortException而被killed。您也可以只处理该异常。检查这并不总是正确的。如果线程在finally块期间中止,它可以跳过释放锁。请看和一些实际设计C#和.NET的人的讨论。