Kara's ongoing quest to tame her codebase continues. First it was serialization, then more strings, then some serial communication.

Today, it's threads.

The original developer was a physicist and an extremely smart person. They never learned too much about databases, but they knew their way around XML, so they had a simple solution to storing data: any time you wanted to save something, rewrite an entire XML file onto disk.

Now, in this case, the "something" being saved is data collected from a piece of scientific equipment. That data is collected by sending commands to the device, changing its state, and asking it for information about readings in that new state.

Since this is a complex, long-running process, the developer used threads. Since it's complex and long running, it needs to be stoppable. And this is how they chose to stop it:

System.Threading.Thread RunThread; enum StopReason { Completed, Aborted, Error } void StopRun(StopReason why) { try { if (RunThread != null) { RunThread.Abort(); } } catch (ThreadAbortException ex) { } finally { if (Thread.CurrentThread != RunThread) { RunThread.Join(); } OnRunStopped(why); } }

You'll note the catch block in there, the catch with absolutely no body. Fun fact: C# lets you omit the catch and do a simple try/finally pair.

Of course, the exception only is an issue because they're calling Abort. In .NET, an aborted thread has no chance to do any cleanup or shutdown. It just ends.

If you were, say, a piece of software that was interacting with a scientific instrument and writing data directly to an XML file, aborting the thread could leave both the instrument and the XML file in unknown, incoherent states.

Which is exactly what happened. Kara changed the stop behavior to actually stop the thread, gracefully.