In case anyone has interested I have confirmed that my intended approach was reasonable. Here are some brief comments that might help others:
Reading from sockets:- It appears an async read (BeginRead) is the way to do this, although the Microsoft documentation for EndRead has a horribly misleading example (discussed elsewhere). The call back allows you to do the same thing as a DataArrival event.
Events:- Event handlers run in the same thread as they are raised (unless your main thread is a windows form in which case you can use Invoke but this is no good if you are writing a service application).
Timers:- For windows NT service applications you can't use the windows timer component. It will let you create one and everything appears ok but it won't fire. Use System.Timers.Timer instead.
Threads:- It also appears that I need to deal with multiple threads whether I want to or not, because both the asynchronous reads and the
VB.NET timer class run their call back functions on separate threads. I use the Monitor class to synchronise DataArrival activities with the main thread activities and other timer activities.