In a typical Windows Forms .NET application, the UI elements are created and updated by the main thread. This thread is also responsible for processing Windows messages. For this reason, it is recommended to keep message processing short and simple. Long running operations performed on this thread will cause incoming Windows messages to queue up. If messages don't get processed in a timely manner, the application will appear hung to the user and provide a poor user experience.
For long running operations, you can offload the work to background threads. However, updating the UI elements from threads other than those that created them will result in an exception being thrown. This is because UI elements can only be updated from the threads that created them. Access to Windows Forms controls is not inherently thread safe. If you have two or more threads manipulating the state of a control, it is possible to force the control into an inconsistent state. Other thread-related bugs are possible, such as race conditions and deadlocks. It is important to make sure that access to your controls is performed in a thread-safe way. More Info
This poses a challenge if you want to update UI elements during those long running operations or as result of them. There are 2 ways to solve this challenge.
- Control.BeginInvoke - MSDN - This allows you to run a specified delegate asynchronously on the thread that created the control.
- BackgroundWorker - MSDN - The class allows you to run an operation on a separate, dedicated thread.
You can force updates to UI elements from other threads using PInvoke\Thread UnSafe methods. These are usually not recommended since the alternative is well established and easy to implement.
Here is a link to the code that shows how to implement either approach. Link on GitHub
Hopefully the two approaches described above will help you implement the correct pattern and update UI elements without any issues.