Personally, I would stick with the producer/consumer approach for this in order to seperate out the UI code from the rest.
Additionally, I would launch a background process (out-of-line via VI server, but I can't find any decent references at the moment) for each CAN so that the communication for each device can run in a seperate thread. This way if one blocks up or generates an error, it won't block the others. These VIs running in the background then send the acquired data via QUEUE to the main program.
I've used this approach in the past for communicating in parallel with many devices and have found it to be very good. The time required to get it up and running is maybe a bit longer, but in the end it's worth it.
So basically, 1 VI 1 device on the level closest to the hardware and then one UI VI which communicates with the others via QUEUEs.
That's my 2c, maybe someone else has a different approach.
Additionally, Sorry I can't give an example of what I mean, or a decent reference but y quick saerch of the forum didn't show me anything useful. With time it'll work, but I don't have too much time at the moment.
Hope this helps
Shane.
Using LV 6.1 and 8.2.1 on W2k (SP4) and WXP (SP2)