简体   繁体   中英

Behaviour of tasks in separate thread on aborting the thread

I've got a special setup with threads and Parallel.Foreach : in a separate thread a Parallel.Foreach loop is executed. It could happen that the Thread will be aborted by calling the function Abort() . I get strange behaviour: multiple times the ThreadAbortException is thrown. Can somebody explain what is happening here and what would be a good solution?

System:

  • Visual Studio 2017
  • C# 7.0
  • .Net 4.6.1

Code below.

static void Main(string[] args)
    {
        //Start the new Thread
        Thread workerThread = new Thread(Program.TestVoid);
        workerThread.Name = "My WorkerThread";
        workerThread.Start();

        //wait
        Thread.Sleep(1000);

        //abort thread
        workerThread.Abort();
    }

    public static void TestVoid()
    {
        bool[] liBools = new bool[10000];

        Parallel.For(0, liBools.Length, idx =>
        {
            liBools[idx] = idx == 9998;
        });

        try
        {
            Parallel.ForEach(liBools, myBool =>
            {
                try
                {
                    //do something
                    Thread.Sleep(1000);
                }
                catch (Exception ex) //Thread Abort Exception get caught
                {

                }
            });
        }
        catch (OperationCanceledException ex)
        {

        }
        catch (ThreadAbortException ex) //Thread Abort Exception get caught
        {

        } //here arises another ThreadAbortException
        finally
        {
            source.Dispose();
        }
        string s = "ready";
    }

The i get a strange behaviour: multiple times the ThreadAbortException is thrown.

This is normal behaviour for that exception:

When a call is made to the Abort method to destroy a thread, the common language runtime throws a ThreadAbortException. ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block. When this exception is raised, the runtime executes all the finally blocks before ending the thread. Because the thread can do an unbounded computation in the finally blocks or call Thread.ResetAbort to cancel the abort, there is no guarantee that the thread will ever end. If you want to wait until the aborted thread has ended, you can call the Thread.Join method. Join is a blocking call that does not return until the thread actually stops executing. ( Source )

what would be a good solution

You can use Thread.ResetAbort() to cancel the abortion at that point, but it's almost always better if you don't call Thread.Abort() . Cancellable Task s and checks on a volatile "please stop now" boolean are two alternatives. Others may be applicable to your use case. Thread.Abort() should be reserved only for press-the-big-red-alert-button scenarios, if that.

If you look at the documentation for Thread.Abort you will see that its function is to throw a ThreadAbortException . If that's not what you want, don't use Thread.Abort . Generally you should exit a thread by gracefully completing/returning from its whole call stack rather than calling Thread.Abort . If you must call Thread.Abort , you should be prepared to handle the exception that goes along with it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM