Speaking as the guy who wrote the queue primitives...
The queues are meant to be the primary means of communicating data in LabVIEW between parallel chunks of code. They are completely thread safe, and they participate with LabVIEW's concurrency scheduling algorithms. They're designed to minimize both data copies and latency and have been stable for many years.
User events go through queues that share most of the code with the general queues, although they have a bit more overhead since at any time there might be multiple listeners for an event, which can (not necessarily "will", just "can") cause more data copies. User events are data broadcasters, where as general queues are data point-to-point transmitters. The general queues thus have less overhead, but it is a very small amount less overhead.
For me personally, I prefer the general queues instead of the user events only because of the arcane nodes and special terminals that are required to register dynamic user events. I use user events when I need to have code that sleeps on both UI events and data arrival. But it is really personal preference -- many programmers are successful using user events generally.