How do I suppress a thread.abort() error C#?
Asked Answered
A

8

5

I am showing a splash screen on a background thread while my program loads. Once it loads I am aborting the Thread as it's only purpose was to show a Now Loading splash form.

My problem is that when aborting a Thread it throws a ThreadAbortException that the user can just click Continue on.

How do I deal with this? I was trying to suppress it like so -->

            try
        {
            Program.splashThread.Abort();
        }
        catch(Exception ex)
        {

        }

but I have a feeling that is going to get me yelled at here and it doesn't work any way.

Thanks!

Atalie answered 4/6, 2009 at 14:48 Comment(3)
I actually just recently blogged about creating a splash screen. See if this can help you out: crazorsharp.blogspot.com/2009/06/… </self_promotion>Jimerson
If you need to use Thread.Abort you're doing something wrong (generally). Try to find a different, safer way. Lots of good suggestions below.Selmner
@BFree: If I could I would give you share in the answer! Thank you for the constructive feedback. I am learning so much already from your post! While the other answer got my current solution to work I expect I will create a more robust Splash from the info in your blog. Thank you!Atalie
N
20

You don't need to cancel the thread. I'll exemplify with code.

In the splash screen form:

public void CloseSplash()
{
    Invoke((MethodInvoker)delegate
    {
        this.Close();
    });
}

In the Program.cs file:

private static Splash _splash = null;
public static void CloseSplash()
{
    if (_splash!= null)
    {
        _splash.CloseSplash();
    }
}

Now, when your Main method starts, show the splash in a thread:

Thread t = new Thread(new ThreadStart(delegate
{
    _splash = new Splash();
    _splash.ShowDialog();
}));

t.Start();

...and when you want it to close, just close it:

Program.CloseSplash();

Then you don't need to worry about aborting the thread; it will exit gracefully.

Naive answered 4/6, 2009 at 14:59 Comment(1)
Thank you for showing me a better way to do this. The constructive feedback is greatly appreciated!Atalie
W
9

Please refer to the following link obtained doing a Google search (first result returned):

http://msdn.microsoft.com/en-us/library/5b50fdsz.aspx

Pay special attention to this part:

When this method is invoked on a thread, the system throws a ThreadAbortException in the thread to abort it. ThreadAbortException is a special exception that can be caught by application code, but is re-thrown at the end of the catch block unless ResetAbort is called. ResetAbort cancels the request to abort, and prevents the ThreadAbortException from terminating the thread. Unexecuted finally blocks are executed before the thread is aborted.

Windfall answered 4/6, 2009 at 14:52 Comment(1)
I was just about to post this. In other words, what he wants to do is likely impossible.Culler
W
7

Using Threadabort is not recommened. It's evil. Why not use another mechanism like an (Auto/Manual)ResetEvent? Start the thread with the splash-screen, wait on the event. If the other code is done loading stuff, set the event en allow the splash-screen to close itself the normal (nice) way.

Watthour answered 4/6, 2009 at 14:53 Comment(1)
Took the words right out of my mouth ;-) I was even going to write that Thread.Abort() is evil, haha.Everyone
B
4

Change the exception type to ThreadAbortException and add a call to ResetAbort()

    try
    {
        Program.splashThread.Abort();
    }
    catch(ThreadAbortException ex)
    {
        Thread.ResetAbort();
    }

In general, aborting threads is considered very bad practice and can lead to all sorts of hard to track down bugs. Have you considered figuring out a way to just close the splash window or use some sort of polling to stop the thread when a flag has been set?

Beckmann answered 4/6, 2009 at 14:50 Comment(1)
If I close the Splash Form and that is ALL the Thread was doing will that dispose of my thread?Atalie
P
4

Some points. The ThreadAbort exception IS the reason the thread aborts. It is not a side effect of you calling abort. When you call abort on a thread, the runtime forces a threadabort exception to be propagated to the thread. This exception can be caught because it allows the user to perform some cleanup before the thread aborts.

The exception is then rethrown automatically to ensure that the thread is aborted. If the exception was caught and if it was not rethrown the thread would never abort.

Really intelligent design actually.

So it is really OK to catch that exception. In fact you should. But catch only that specific exception and not the general exception. (as shown below)

catch(ThreadAbortException ex)
{
   //This is an expected exception. The thread is being aborted
}
Partlow answered 4/6, 2009 at 18:10 Comment(0)
A
1

Why would you do that? Just set a flag that the thread polls, then eventually when the thread picks it up it'll close itself.

Acacia answered 4/6, 2009 at 14:52 Comment(0)
S
1

Try this code. It's working fine for me.

void splash()
{
    try {
        SplashScreen.SplashForm frm = new SplashScreen.SplashForm();
        frm.AppName = "HR";

        Application.Run(frm);
    }
    catch (ThreadAbortException ex)
    {
        Thread.ResetAbort();
    }
}
Shakta answered 9/7, 2017 at 18:2 Comment(0)
D
0

I've used the solution suggested by Fredrik Mörk. It's very clear and elegant. Otherwise I found a problem if we instantiate the splash form before launching the real application (application.run (mainform...)):

it raises an invalidOprationException caused by the form-handle still not exists in the calling-thread. To create the handle directly in the thread t (and skip this exception!) try to launch the splash form in this way:

Thread t = new Thread(new ThreadStart(delegate
{
    _splash = new Splash();
     Application.Run(_splash);
}));

t.Start();

and, if you plan to call the closeSplash method in more branches of the program, force the null value after the first call:

    private static Splash _splash = null;
    public static void CloseSplash()
    {
        if (_splash!= null)
        {
            _splash.CloseSplash();
            _splash=null;
        }
}
Declamation answered 23/7, 2009 at 14:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.