В комментариях указано, что нужна реализация под .NET 2.0. В этой версии фреймворка нужно использовать Thread.
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "Ждем";
new Thread(delegate ()
{
// тут длительные вычисления
Invoke((MethodInvoker)delegate
{
label1.Text = "Готово";
});
})
.Start();
}
В данном примере создается и запускается (вызовом метода Start) отдельный поток. Длительные вычисления выполняются в нём. Тем временем gui-поток может спокойно отрисовывать контролы.
К контролам формы можно обращаться только из того потока, в котором они созданы. Для этого используем метод Invoke. Его вызов посылает сообщение в основной поток gui.
Примечание: внутри делегата Invoke выполняйте только обращение к gui-контролам, не делайте в нём никакие длительные операции.