I've spent the last few days messing around with C# in Visual Studio - I'd been playing with it inside Unity and found that on the whole, I'm quite partial to this language. I started up Visual Studio a couple days ago and was trying to decide what to try in it when I happened upon the documentation for the
SerialPort class, at which point I decided that my OBDII software might be a good candidate.
I'd been running out of Steam on the Python implementation because it still seemed like I was a long way off from even thinking about a UI, and I had some pretty extreme reliability issues with it too. So with the C# one I resolved I'd go in, head-first. Each piece I made, I built a UI to test it with. I also took a very different approach to initializing the interface which turned out to be much more reliable at detecting the device and bringing it to a known state.
One of the things I noticed very early on in using .Net was that I'm almost certainly "doing it wrong". I'm using the TAP design pattern of designating asynchronous tasks, with the main UI thread spending very little time doing any of the actual heavy lifting, which keeps the UI responsive. However my ELM327 library is never going to be properly thread-aware, because it can really only do one thing at a time and you rely on knowing the state of the interface at all times.
So I've implemented a crude state system with the ELM object reporting back to the UI when it has new data or whatever, and it doesn't let you attempt multiple actions at once and so on... but I'm pretty sure it's incredibly poorly implemented and vulnerable to numerous race conditions, and I'll probably have to build out a proper locking system and most likely a queue of some sort.
I might try and track down someone well-versed in C# who can take a look at it and point out all the things I'm doing wrong - I think it's okay for only having about 48 hours with the language under my belt, but I'm sure there is lots of things that'll make seasoned vets roll their eyes. For now though, it mostly does what it says on the box (though I'm only testing it with test data, I've not taken my laptop out and hooked it up to a vehicle yet).
The only thing the Python version does that the C# version doesn't yet is the live data PIDs. I'm not sure how I'm going to implement that, as it's a lamba-and-regex monstrosity which at the time I thought was a nifty way to solve the problem. I might be able to do something like that in C#, or it might turn out being a fuckin' great big switch/case statement. I am planning on using (perhaps sourced via SQLite) a data store of some sort to track the meanings of the codes and so on as well.
I haven't gotten around to implementing unit tests for any of it yet, which is another thing I should probably do.