So presumably I can have the interrupt function change the state of a variable, and upon that state change have the loop start back at the beginning of the solenoid array?
Yes, and no. The ISR can change the state of a variable. However, when the ISR ends, control returns to the instruction following the one that had been executing when the interrupt occurs, not to the start of loop. If the code had been in a delay, the delay will resume.
You really should get rid of the delay(). If you were controlling the solenoids manually, you could use an egg timer to determine whether the solenoid had been open long enough, or you could use a watch and a notepad.
If you are using the egg timer, you open the solenoid, flip the timer over, and watch the timer. You can't do anything else, then, except watch the timer, so you can shut the solenoid off when the sand all runs down.
If you use a watch and paper, you write down the time that you open the solenoid. Periodically, you check your watch, and compare it to the time that you wrote down. If it is time, you turn the solenoid off. Meanwhile, though, you can read a book or watch TV, as long as you check your watch and the delta time fairly often.
The delay function is like the egg-timer. The millis() function is like your watch. A variable to hold the time replaces the note pad.
Since you're no longer tied up in long delay()s, you might not even need the interrupt handlers anymore. You can poll the pins, instead, reducing the complexity of the code significantly.