There are a couple of basic rules of Windows forms programming that you need to learn first. Once you understand them, you should understand why what you are doing won't work, and what you need to do to make it work.
Every Windows Forms app has what is called the UI thread (UI standing for User Interface, of course). It is typically the first thread started by the program, but I suppose it doesn't have to be.
The job of the UI thread is to....well, manage the user interface. It responds to user actions like mouse clicks and keyboard input, and it does stuff to update what the user sees on the screen. The key thing to know about the UI thread is that if it does something that takes a long time, then it will appear that your program is hung. If the user hits the 'A' key, and you spend 60 seconds doing something wonderful for the user because they hit that key, then for that entire 60 seconds, your program will appear to be hung. You can do all sorts of stuff, like updating text boxes and gas gauges and listboxes, but none of that stuff will actually show up on the screen, because painting the screen is something that happens when the UI thread is NOT busy.
The second rule you need to know is that *ONLY* the UI thread is allowed to update the user interface. You can't spin up another thread and have it start changing the value of label1.Text. Only the UI thread can do that.
SO...if you have a long running task to do, you can't put it in the UI thread, because that will make your program appear to be hung.
So you move the work into a thread. Problem solved, right? But then the thread wants to update the UI, but it can't, because it isn't the UI thread. Almost sounds like a Catch-22.
What to do? Well, this is where the functions Invoke, InvokeRequired and BeginInvoke come into play. You need to learn what they are all about and how to use them. But basically your thread might call a function, and that functions tests to see if InvokeRequired is true. If it is, it means that you need to switch from the current thread to the UI thread to finish your task. You do that with Invoke, or BeginInvoke. Then, everybody is happy. The UI update gets done by the UI thread. The worker thread does its time consuming work without blocking the UI.
Google InvokeRequired and you should find more than enough examples of how to do it.