A worker thrread that communicates with the GUI
    These threads can call functions that block withouth affecting the GUI (a good thing)
    Note that this function is the code started as each thread. All threads are identical in this way
    :param thread_name: Text name used  for displaying info
    :param run_freq: How often the thread should run in milliseconds
    :param gui_queue: Queue used to communicate with the GUI
    :return:

def worker_thread(thread_name, run_freq,  gui_queue):
    """
    A worker thrread that communicates with the GUI
    These threads can call functions that block withouth affecting the GUI (a good thing)
    Note that this function is the code started as each thread. All threads are identical in this way
    :param thread_name: Text name used  for displaying info
    :param run_freq: How often the thread should run in milliseconds
    :param gui_queue: Queue used to communicate with the GUI
    :return:
    """
    print('Starting thread - {} that runds every {} ms'.format(thread_name, run_freq))
    for i in itertools.count():                             # loop forever, keeping count in i as it loops
        time.sleep(run_freq/1000)                           # sleep for a while
        gui_queue.put('{} - {}'.format(thread_name, i))     # put a message into queue for GUI
        print('..')