I’m struggling to eliminate app.DoEvents in my app, but have not been able to find a way to do it. My app implements a handshaked protocol (MIDI sysex) with external hardware devices via MIDI-over-USB. Every sysex message I send must receive a handshake from the external device within 50ms. While waiting for that handshake, I don’t want my program to be doing anything except waiting - it either gets a handshake or it times out; control cannot be returned to the main event loop until one of those things happens.
The lowest level of MIDI-over-USB is handled by a third-party (Monkeybread) plugin whose Read event fires whenever a 3 or 4-byte packet is received. My code in the read event parses those into sysex messages, which are delimited by special characters. Each time a message is parsed it’s appended to a buffer array.
In pseudocode my main app’s code is typically something like this:
SendSysexMessage // I send data to the device
result = GetSysexMessage // I need a handshake or timeout before I can do anything else
proceed with execution based on result
GetSysexMessage looks like this:
Initialize timeout and clear buffer
Do
If timeout then return nomessage
If Ubound(Buffer) >=0 then return Buffer(0)
app.DoEvents
Loop
With DoEvents it works fine apart from the occasional random quit. Without DoEvents GetSysexMessage never sees that something has been added to the buffer, and/or nothing ever gets added to the buffer, depending on how I’ve structured things.
I’ve tried putting the plug-in and its event handler code into a thread, but this does not solve the problem. The plugin is receiving data, parsing it, and appending messages to the buffer, but without DoEvents, GetSysexMessage never sees that they’ve been added. I’ve tried making the buffer a global property rather than a property of the thread. I’ve read extensively on thread use but it’s always about keeping the UI alive with a timer in a thread while the thread works on a time-consuming process; I think my situation is different. I’ve envisioned all sorts of structures using threads and/or timers, but ultimately I run up against the fact that somewhere, my app needs to wait in a loop while allowing other code (the message receiver/parser) to execute, while at the same time being able to access properties (the message buffer or a flag) of other parts of the program from within the waiting loop. DoEvents performs exactly the desired function, but brings with it some instability.
Any thoughts?
Thanks,
Julia