C# 线程中止异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1856286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 21:25:34  来源:igfitidea点击:

ThreadAbortException

c#.net

提问by Overdose

Let's say we have some code like this running in the separate thread:

假设我们有一些这样的代码在单独的线程中运行:

private static void ThreadFunc() {
    ulong counter = 0;

    while (true) {

        try {
            Console.WriteLine( "{0}", counter++ );
        }
        catch (ThreadAbortException) {
            Console.WriteLine( "Abort!" );
        }

    }
}

When Thread.Abort()is called, is it possible that the exception is thrown outside of catch block?

什么时候Thread.Abort()调用,有没有可能在catch块之外抛出异常?

采纳答案by Josh

Actually yes, a ThreadAbortExceptionis special. Even if you handle it, it will be automatically re-thrown by the CLR at the end of the try/catch/finally. (As noted in the comments, it can be suppressed with ResetAbortbut by that point the code smells like rotten fish.)

实际上是的,aThreadAbortException是特殊的。即使你处理了,也会在try/catch/finally结束时被CLR自动重新抛出。(如评论中所述,它可以被抑制,ResetAbort但到那时代码闻起来像腐烂的鱼。)

Not to mention even though there is no obvious executable code outside of your try/catch/finally, every iteration of the loop winds up outside of the scope for a small duration so the abort could occur outside of your try block.

更不用说即使在 try/catch/finally 之外没有明显的可执行代码,循环的每次迭代都会在范围之外结束一小段时间,因此中止可能发生在 try 块之外。

Unless you are actually doing something in the catch block, I would just make a try/finally and don't worry about ThreadAbortException. There are much better ways of aborting a thread without using Thread.Abortwhich not only chaotically interrupts your code at an unpredictable point, it's also not guaranteed to work because if your thread is currently calling out to some unmanaged code, the thread will not abort until control returns to managed code.

除非您实际上在 catch 块中执行某些操作,否则我只会尝试/finally 而不必担心ThreadAbortException. 有很多更好的方法可以在不使用的情况下中止线程,Thread.Abort这不仅会在不可预测的点混乱地中断您的代码,而且也不能保证工作,因为如果您的线程当前正在调用某些非托管代码,则该线程在控制返回之前不会中止到托管代码。

It's much better to use some type of synchronization primitive such as a ManualResetEventto act as a flag telling your thread when to exit. You could even use a boolean field for this purpose which is what the BackgroundWorker does.

使用某种类型的同步原语(例如 a )ManualResetEvent作为告诉线程何时退出的标志要好得多。为此,您甚至可以使用布尔字段,这正是 BackgroundWorker 所做的。

回答by Andrew Hare

I am not 100% what you are asking but I wanted to point out that you will never be able to swallow a ThreadAbortException:

我不是 100% 你要问的,但我想指出你永远无法吞下ThreadAbortException

When a call is made to the Abort method to destroy a thread, the common language runtime throws a ThreadAbortException. ThreadAbortExceptionis a special exception that can be caught, but it will automatically be raised again at the end of the catch block.

当调用 Abort 方法来销毁线程时,公共语言运行时会抛出一个 ThreadAbortException. ThreadAbortException是一个可以被捕获的特殊异常,但它会在 catch 块的末尾自动再次引发。

Are you asking if it is possible to catch a ThreadAbortExceptionthat is thrown in another thread here with a try/catch? If that is your question, then no, you cannot.

您是在问是否有可能用 a 捕获ThreadAbortException在另一个线程中抛出的 a try/catch?如果这是你的问题,那么不,你不能。

回答by Jon Skeet

Yes. I suspectthat you're asking because thread interruptionsonly occur when a thread could otherwise block (or if it's already blocked) - e.g. for IO.

是的。我怀疑您之所以这么问是因为线程中断仅在线程可能会阻塞(或者它已经被阻塞)时才会发生 - 例如对于 IO。

There's no such guarantee for abort. It can happen at any time, basically, although there are delay-abortregions such as constrained execution regionsand catch/finally blocks, where the abort request is just remembered, and the thread aborted when it exits the region.

中止没有这样的保证。它可以在任何时间发生,基本上,尽管存在延迟中止区域,例如受限执行区域和 catch/finally 块,其中中止请求仅被记住,并且线程在退出该区域时中止。

Synchronous thread aborts (i.e. aborting your own thread) is reasonably safe, but asynchronous aborts (aborting a differentthread) are almost always a bad idea. Read "Concurrent Programming on Windows" by Joe Duffyfor further information.

同步线程中止(即中止您自己的线程)相当安全,但异步中止(中止不同的线程)几乎总是一个坏主意。阅读Joe Duffy 的“Windows 上的并发编程”以获取更多信息。

EDIT: As noted by Eric below, aborting another thread isn't guaranteed to actually have any effect either. Just to quote the comment:

编辑:正如下面 Eric 所指出的,中止另一个线程也不能保证实际上有任何影响。只是引用评论:

I would have said that the thread is aborted ifit exits the region, emphasizing that Thread.Abortis completely unreliable. A thread which being aborted because it is stuck in an infinite loop will not abort if the loop is in such a region. This is yet another reason why Thread.Abortis a bad idea; if you can't rely on the desired effect actually happening then why would you call the method?

我会说如果线程退出该区域就会中止,强调这Thread.Abort是完全不可靠的。由于陷入无限循环而被中止的线程如果循环位于这样的区域中,则不会中止。这是Thread.Abort一个坏主意的另一个原因;如果您不能依赖实际发生的预期效果,那么您为什么要调用该方法?

回答by Ilya Builuk

Actually, ThreadAbortExceptionis special in case it's thrown by CLR or Thread.Abortmethod. Compare output:

实际上,ThreadAbortException是特殊的,以防它被 CLR 或Thread.Abort方法抛出。比较输出:

  • Slightly modified example (added Console.WriteLine) from Joe Duffy's "Concurrent Programming on Windows". It throws the exception by Thread.CurrentThread.Abort:
    
    try
    {
        try
        {
            Thread.CurrentThread.Abort();
        }
        catch (ThreadAbortException)
        {
            Console.WriteLine("First");
            //Try to swallow it.
        } //CLR automatically reraises the exception here .
    }
    catch (ThreadAbortException)
    {
        Console.WriteLine("Second");
        Thread.ResetAbort();
        //Try to swallow it again .
    } //The in - flight abort was reset , so it is not reraised again .
    
    
    
    Output:
    First
    Second
    
  • Modify previous example to use different approach of ThreadAbortException instance creation:
    
    try
    {
        try
        {
            // get non-public constructor
            var cstor = typeof(ThreadAbortException)
                .GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
            // create ThreadAbortException instance
            ThreadAbortException ex = cstor.Invoke(null) as ThreadAbortException;
    
            // throw..
            throw ex;
        }
        catch (ThreadAbortException)
        {
            Console.WriteLine("First");
        } 
    }
    catch (ThreadAbortException)
    {
        Console.WriteLine("Second");
        Thread.ResetAbort();
    } 
    
    Output:
    First
    
  • 来自 Joe Duffy 的“Windows 上的并发编程”的稍微修改的示例(添加了 Console.WriteLine)。它通过 Thread.CurrentThread.Abort 抛出异常:
    
    try
    {
        try
        {
            Thread.CurrentThread.Abort();
        }
        catch (ThreadAbortException)
        {
            Console.WriteLine("First");
            //Try to swallow it.
        } //CLR automatically reraises the exception here .
    }
    catch (ThreadAbortException)
    {
        Console.WriteLine("Second");
        Thread.ResetAbort();
        //Try to swallow it again .
    } //The in - flight abort was reset , so it is not reraised again .
    
    
    
    输出:
    First
    Second
    
  • 修改前面的示例以使用不同的 ThreadAbortException 实例创建方法:
    
    try
    {
        try
        {
            // get non-public constructor
            var cstor = typeof(ThreadAbortException)
                .GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
            // create ThreadAbortException instance
            ThreadAbortException ex = cstor.Invoke(null) as ThreadAbortException;
    
            // throw..
            throw ex;
        }
        catch (ThreadAbortException)
        {
            Console.WriteLine("First");
        } 
    }
    catch (ThreadAbortException)
    {
        Console.WriteLine("Second");
        Thread.ResetAbort();
    } 
    
    输出:
    First
    

It seems like Thread'smethods call native code internally which makes raised exception specific.

似乎Thread 的方法在内部调用本机代码,这使得引发的异常特定。