For this task will an asynchronous function be required?

I need to run a task for an experiment where there will be two pictures displaying on the screen at alternating times. Pic 1 will display for 2 seconds then pic 2 for 2 seconds, pic 1 for 2 seconds, etc. and the program needs to move on to the next trial (next two pictures) when either the participant presses a button to say they have seen a difference between the two pictures or when a 60 second time limit runs up.

So I need the 60 second time limit timer to be running at the same time as the images are alternating every 2 seconds and while also ensuring that the program moves on to the next trial and records the response time if the participant presses a keyboard key instead of the time limit being reached.

So I’m wondering if I will need to do some kind of asynchronous function to accomplish this because there are a few time-dependent processes occurring all at once. Will I need to make the 60 second time-limit timer run in the background while the current trial is displaying on the screen? And then will I need to make another asynchronous function for when the images show up on the screen as well since the participant is supposed to be pressing a key while the code to display the image for 2 seconds is running. Is there a way to alternate the images every 2 seconds while also being able to pick up on a keyboard press at the same time?

Thank you in advance for any help!

You don’t need to run a timer, just a loop that displays images, check keyboard inlut and checks how much time has already elapsed, breaking out of the loop when one of your trial end conditions is reached

Thank you for the response.

So do you mean that I should have a while loop with the conditions like this:

While ( time < 60 seconds && key not pressed )
     alternate pictures every 2 seconds

If this is the case, where would I monitor for when the key is pressed?

or do you mean this:

while true
     if ( key is pressed )
           record time; 
     if (time >= 60 seconds)

And if this is the case, where in here would I put the code that controls the flipping between images every 2 seconds? It seems like this code would need to be running in the background somehow.

You can do multiple things inside a while loop and either use a conditional while x or just break when any of your conditions match:

isRunning = true
drawA = true
startTime = Screen('Flip');
while isRunning
    if drawA; draw(stimulusA); else; draw(stimulusB); end
    thisTime = Screen('Flip')
    keyPressed = checkKeyboard;
    if timeToChangeStimulus(thisTime); drawA = ~drawA; end
    if (thisTime - startTime) > 60; isRunning = false; end % you can also just break here
    if (keyPressed); isRunning = false; end % you can also just break here

And in case you are worried that keypress checks would now be done at wcreen refresh rate and be too coarse, you can look into the KbQueue functions for implementing checkKeyboard. They run asynchronously in the background and are thus not stuck to screen refresh.

Thank you for the reply!

I am still a little bit unsure if I’m doing this in the best way. I followed your advice and implemented the loop like you have written but now I’m not really sure if I’m doing the timeToChangeStimulus() function in a good way. Right now I have 3 lists in that function: an imageOne list, a greyScreen list and an imageTwo list. These lists contain intervals where the screen should display the cooresponding image or grey screen between images. For simplicity I said 2 seconds for each image before but its actually 560ms per image and 80ms for a grey screen in between. Here’s the function:

function stimulus = timeToChangeStimulus(time, startTime)

    picOneIntervals = {[0, 560], [1200, 1760], [2400, 2960], [3600, 4160], [4800, 5360]};
    greyIntervals   = {[560, 640], [1760, 1840], [2960, 3040], [4160, 4240], [5360, 5440]};
    picTwoIntervals = {[640, 1200], [1840, 2400], [3040, 3600], [4240, 4800], [5440, 6000]};

    for interval = picOneIntervals
        if (time - startTime)*1000 >= interval{1}(1) && (time - startTime)*1000 <= interval{1}(2)
            stimulus = 1;

    for interval = greyIntervals
        if (time - startTime)*1000 >= interval{1}(1) && (time - startTime)*1000 <= interval{1}(2)
            stimulus = 2;

    for interval = picTwoIntervals
        if (time - startTime)*1000 >= interval{1}(1) && (time - startTime)*1000 <= interval{1}(2)
            stimulus = 3;


This function then returns a 1, 2 or 3 so the first function knows which image to display.

Is there a better way I can approach this task? Thank you.

What problem are you trying to solve? It could probably be done shorter, but code that works and you can understand is the best code