I developed an object for my BCD996T's control program (a touchscreen interface that also controls my Kenwood TS2000 and TMD700). I don't think that radio has any asynchronous, i.e., non-predictive, I/O. To wit, everything it tells you is in response to a set or query command. I understand that the 996 is similar to the 396 [I'll check on the VOL and SQL commands to see if they're asynch].
I derived all three objects from a more generic class (a series of derived classes, actually) written to handle asynchronous radios, like the TS2000 or TMD700A. And while it certainly works fine for keeping up with the radio's reception status, etc. (e.g., the GID, GLG, and STS commands, where you don't care about tying a particular query to a particular response, and even other query versions of a lot of the other commands), the asynch model does not work well for many [most?] commands (especially "set" commands, like deleting a system or adding a new group, where you _do_ need to associate a particular response with a particular command), and it does not at all for a few commands (like the commands that enumerate the locked out frequencies, etc.)
My object model is:
Radio ->
....SerialRadio ->
........AsynchSerialRadio ->
............TMD700A
............TS2000
............BCD996T
The AsynchSerialRadio objects use two background threads, a writer thread, which pulls strings from a managed Queue object (which is itself synchronized with lock{}s and an event object to signal addition of elements) and writes them to the serialport, and a reader queue, which pulls strings from the serialport and parses them and invokes the appropriate method for the received command. The UI then uses a third thread (the main thread, actually) to manage interaction between the user and the radio objects. Every time the reader thread changes the radio's object, it fires off a notification event that the UI thread hooks into to receive notifications of changes in properties of the radio's object, to, e.g., update the screen, etc.
I started work on a SynchSerialRadio class derived from the SerialRadio class that would follow a synchronous model, and I might eventually switch to that model for the BCD996A class, since the radio is, as far as I can tell, purely synchronous. This model would necessitate deciding, for example, how to handle read timeouts, how to keep reads and writes synchronized, etc., but would obviate the problems with trying to follow an asynch model for a radio that isn't at all asynchronous.
...R