Quando devo fare questo genere di cose, il pattern che uso io è questo (pseudo c#, ma si capisce)

codice:
private procedura_che_fa_operaioni_lunghe(..)
{
    BackgroundWorker bgw = new Backgroundworker();
    
    //Lavoro da fare nel thread secondario
    bgw.DoWork += (s, e) =>
    {
        //Operazioni lunghe. Occhio a non toccare elementi grafici qui.
    }

    //Operazioni da fare non appena si ritorna al thread principale.
    //Qui sei nel 3d principale, puoi tornare a toccare gli elementi grafici, per esempio...
    bgw.RunWorkerCompleted += (s, e) =>
    {
        Formloading.Close();
    }

    //Operazioni da fare subito prima di eseguire le operazioni in multithreading
    Formloading.ShowDialog();

    //Eseguo il bgw.
    bgw.RunWorkerAsync();
}
Per una completa trattazione del BGW (tipo passaggio parametri tra i due thread, e altro ancora) msdn o google sono pieni zeppi di esempi.