Question

First of all, Thread.Abort() is evil - got it! Now let me explain my situation...

Situation:

I have a dashboard that only displays current running status to the user. It executes various select queries against a Sql Server DB and performs some calculations that are eventually displayed to the user on the dashboard. The user can open multiple dashboards at the same time. I have a timer thread that refreshes the dashboard every few seconds. That timer thread spawns another thread (actually queues work on a threadpool) to perform long running calculations/queries.

The Problem:

When the user clicks the X to close the Dashboard window, it needs to shut down right away (say within a second, I think 2 seconds is too long). So I use this code:

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        _timerThread.Abort();
    }

    private void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        // we're on the timer thread now

        try
        {
            RefreshUi();
        }
        catch (ThreadAbortException)
        {
            System.Threading.Thread.ResetAbort();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

The problem is sometimes the ThreadAbortException is caught, and sometimes it isn't. I find it's mostly uncaught when in the middle of executing queries.

[UPDATE] I've recently discovered I can catch the ThreadAbortException if I check the innerexception.

Questions:

  1. Is it ok use Thread.Abort() in this case? If so, how do I ALWAYS catch the ThreadAbortException so the user doesn't see it when closing the Form? (from what I've read I don't think this is possible)
  2. If it's not ok to use Thread.Abort() (which is what I think most of you will answer), then here are my other concerns with using a "global boolean flag" to tell the thread(s) when to shutdown.
    • I'm concerned the threads won't stop themselves within the 1 second time limit. (For example, I may have some queries that take 1-2 seconds to run)
    • I will have to clutter my code with: if(shouldShutdown) statements.
    • Should I make the shouldShutdown flag static so all my classes can use it? Will this pose a problem if the user can open multiple dashboards at the same time? (I'm concerned about the static variable being shared across all dashboards. This I definetely don't want.)
    • When the worker threads see they have to shutdown, should they throw an exception or just return? If they just return, then I'll have to add even more if(shouldShutdown) checks because it's ok for some functions to return false. If throwing an exception is ok, which exception do you recommend? A custom one?

Thanks

Was it helpful?

Solution

Right way to do this will be

  1. Making all requests to SQL server asynchronous
  2. Having ManualResetEvent handled in background threads and fired from main thread when it's time to close.
  3. Interrupting sql requests in AutoResetEvent handlers and gracefully exiting threads
  4. Making GUI close windows in parallel with exiting the threads, so they not depend of each other.
  5. If closing your dashboard means exiting process it will be good to wait all the threads to exit while having windows closed.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top