Using DMA is the best option. Basically you set up a buffer, start the DMA, and you get an interrupt when it completes although the MQX driver hides some of these details.
Interrupt driven is better than polling as the interrupt code runs only when the SPI peripheral has received new data or has an empty buffer for new data to be shifted out. It just sucks to get an interrupt on every word.
Polling is the least desirable approach. In is incredibly inefficient but if you are just trying to get some basics working can be acceptable. I'd say the real problem with it is making sure you don't drop data and that means you need to give it high task priority and that means giving priority to some loop that is constantly asking if data is available.
But to address your question: Where is it hanging? When it hangs you should be able to halt the processor, choose the polling task from the MQX plug-in, and find the exact spot where that code is hanging. The plug-ins are very powerful.
Regarding your stacks. Again, use the plug-in to view the stack usage for each individual stack. It'll tell you right away if one has overflowed.
My opinion is to spend some time learning how to use DMA. Find the maximum SPI clock speed that both the processor and the LCD will accept and burst those frames over. And use a scope to verify things.
Best of luck,
Kenny