Rozwiązanie, jakie zaimplementowałeś można porównać z tym: "Jest tyle głodu na świecie. Ale wystarczy odwrócić wzrok i wszystko jest ok". Na GUI może operować tylko wątek, który to GUI utworzył (w Twoim przypadku główny wątek aplikacji). Nie możesz odwoływać się bezpośrednio do gui z innego wątku - to skutkuje błędem. I dobrze. Aby z innego wątku zrobić coś na gui musisz posłużyć się synchronizacją. W tym przypadku użyć BeginInvoke. Ja to robię w taki sposób (kod pisany z palca, więc może nie działać, ale zasada jest widoczna):
public void SetStatus(string msg)
{
if(InvokeRequired)
BeginInvoke(new Action(
() =>
{
DoSetStatus(msg);
}
));
else
DoSetStatus(msg);
}
void DoSetStatus(string msg)
{
statusLabel.Text = msg;
}
Małe wytłumaczenie.
Inne obiekty (w tym w innych wątkach) wywołują metodę SetStatus. Ona sprawdza, czy została wywołana ze "swojego" wątku, czy z jakiegoś innego (InvokeRequired). Jeśli ze swojego, to po prostu wywołuje DoSetStatus, bo bezkarnie może sobie gmerać w gui. Jeśli z innego, to wtedy wywołuje DoSetStatus za pośrednictwem BeginInvoke. BeginInvoke, z tego co rozumiem, dodaje po prostu nowy komunikat do pętli komunikatów okna. Wykonanie kodu w BeginInvoke nie będzie więc natychmiastowe, ale z pewnym opóźnieniem. Natomiast użytkownik w ogóle tego opóźnienia nie zobaczy.
Tak to się robi poprawnie.