LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Acquisition Thread Delayed by main thread ?

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 10"><meta name="Originator" content="Microsoft Word 10">

Hi I have the following setup. I have created a new thread from the default thread pool to do my acquisition. I basically move a stage and take a camera image to build up a large image of a region.
Each time I move the stage and get a camera image. I then add this image to a thread safe queue.

I have also setup a callback to be called when data is written to the queue. This callback should get called in the main ui thread I believe, so it is where I display the images.

My problem is that the callback seems to interrupt the acquisition thread. I.e. if I get the callback to be called when 5 items are added to the queue the stage moves 5 times with now delay, but on the fifth there is a delay when I remove the items from the queue and display them.

Should the acquisition thread be able to continue with any delay?
PS this is a multi processor machine.

If I put a Delay(2.0) call in the callback function it also clearly delays the acquisition thread.

Does anyone have any ideas?

0 Kudos
Message 1 of 8
(4,106 Views)

Hi Glenn.

It seems to me that you have set the threshold values for both the acquisition and main thread callbacks to be equal to the maximum TSQ length (which is apparently 5), so that:

  • the callback for EVENT_TSQ_ITEMS_IN_QUEUE will not fire (in the main thread) until the queue length reaches 5
  • the callback for EVENT_TSQ_QUEUE_SPACE_FREE will not fire (in the acquisition thread) until the queue is empty

This would explain the delays you have observed, and may also cause problems with handling the last few images.

I suggest you try something like this:
// In your acquisition thread:
CmtInstallTSQCallback (tsqHandle, EVENT_TSQ_QUEUE_SPACE_FREE, 1,
        AcquireNextImageCallback, NULL,
        CmtGetCurrentThreadID(), NULL);
// In your main thread:
CmtInstallTSQCallback (tsqHandle, EVENT_TSQ_ITEMS_IN_QUEUE, 1,
        ProcessNextImageCallback, NULL,
        CmtGetCurrentThreadID(), NULL);

Keep the maximum queue length as is, so that user interface activity has minimal impact on the acquisition.

Hope this helps.

Regards,
Colin.

0 Kudos
Message 2 of 8
(4,068 Views)
Well this is what I have

static int CVICALLBACK AcquisitionThread(void *data)
{
    // Thread controlling the xy stage.
    // Does a stage move as soon as the previous acquisition is complete.
   ........
   // Get image create tile etc
   tile = ....
   ...............       

   CmtWriteTSQData(rs->queue, &tile, 1, TSQ_INFINITE_TIMEOUT, &number_flushed);
}


static void CVICALLBACK QueueReadCallback (int queueHandle, unsigned int event, int value, void *callbackData)
{
    if(event != EVENT_TSQ_ITEMS_IN_QUEUE)
        return;
   
    // Removes the tiles from the queue
    if((items_in_queue = CmtReadTSQData (rs->queue, tiles, items_in_queue, 20, 0)) < 0)
        return;  

   Delay(2.0);

    for(i=0; i < items_in_queue; i++) {
       
        tile = &(tiles[i]);
        // Process tile in main thread
    } 
}


void Run()
{
      CmtInstallTSQCallback (rs->queue, EVENT_TSQ_ITEMS_IN_QUEUE, 1, QueueReadCallback, rs, CmtGetCurrentThreadID(), &id);
      
      CmtScheduleThreadPoolFunction(DEFAULT_THREAD_POOL_HANDLE, AcquisitionThread, rs, &acquisition_thread_id);     
     
      CmtWaitForThreadPoolFunctionCompletion (DEFAULT_THREAD_POOL_HANDLE, acquisition_thread_id,
                OPT_TP_PROCESS_EVENTS_WHILE_WAITING);
}


I still get the delay though with one item added at a time ?

Maybe I misunderstood your answer though.

Thanks for the help.

Glenn
0 Kudos
Message 3 of 8
(4,053 Views)
Hi Glenn.

It looks like AcquisitionThread() is called repeatedly to acquire the entire image. Is this correct?
If so, the delays you see are probably due to the overhead of continually scheduling this function. Try placing the repeated steps inside a loop:

static int CVICALLBACK AcquisitionThread(void *data)
{
  // Initialise
  ...
  while (acquiringImage)
    {
    // Does a stage move as soon as the previous acquisition is complete.
    ........
    // Get image create tile etc
    tile = ....
    ...............       

    CmtWriteTSQData(rs->queue, &tile, 1, TSQ_INFINITE_TIMEOUT, NULL);  // I assume you are not using auto flush
    }

  // Complete image processed, so clean up and return
  ...
}

With this logic, you won't need the
EVENT_TSQ_QUEUE_SPACE_FREE callback.

Have a look at the BuffNoDataLoss sample project in the Samples\Utility\Threading\ThreadSafeQueue folder. You don't need all of its bells and whistles, but the basic structure appears suitable for your application.

Good luck.

Colin.

0 Kudos
Message 4 of 8
(4,039 Views)
No it only schedules the acquisition thread once.

The acquisition thread sits in a while loop until the stage has moved over a large region.
So it continues to add images to the queue for each image that makes up one large region.

static int CVICALLBACK AcquisitionThread(void *data)
{
  // Initialise
  ...
  while (x, y in rows * cols)
    {
    // Does a stage move as soon as the previous acquisition is complete.
    ........
    Move to x y

    // Get image create tile etc
    tile = ....
    ...............       

    CmtWriteTSQData(rs->queue, &tile, 1, TSQ_INFINITE_TIMEOUT, NULL);  // I assume you are not using auto flush
    }

  // Complete image processed, so clean up and return
  ...
}

Putting the Delay in the read callback definitely stops the stage from moving for the length of time specified in Delay function even though it is a different thread ?



0 Kudos
Message 5 of 8
(4,031 Views)
Ah hangon. Writing that previous reply has helped me wake up.
I communicate with the stage through a com port I have locks protecting that ComWrt so I can communicate with it through different threads.

Maybe keeping the main thread occupied is preventing the processing of the comport data ?
0 Kudos
Message 6 of 8
(4,030 Views)
No the comport is interrupt driven so it should be ok.
0 Kudos
Message 7 of 8
(4,029 Views)
I'm not using auto flush by the way.
0 Kudos
Message 8 of 8
(4,027 Views)