This lets us go back to the previous, simpler Calc Pi: Because Invoke is a synchronous call and we're not consuming the return value (in fact, Show Progress doesn't have a return value), it's better to use Begin Invoke here so that the worker thread isn't held up, as shown here: Begin Invoke is always preferred if you don't need the return of a function call because it sends the worker thread to its work immediately and avoids the possibility of deadlock.
I've used this short example to demonstrate how to perform long-running operations while still showing progress and keeping the UI responsive to user interaction.
So robust, in fact, that it gracefully handled my violation of the prime directive of Windows programming—Though shalt not operate on a window from other than its creating thread.
That's why even my little application has a progress bar.
The algorithm I'm using calculates pi nine digits at a time. The problem, of course, is that my application is single-threaded, so while the thread is calculating pi, it can't also be drawing the UI.
However, the function we want to call to update the UI, Show Progress, takes three arguments, so we'll need the second overload.
We'll also need another delegate for our Show Progress method so that we can pass the arguments correctly.
Here's how to use Invoke to make sure that our calls to Show Progress, and therefore our use of our windows, shows up on the correct thread (making sure to replace both calls to Show Progress in Calc Pi): The use of Invoke has finally given me a safe use of multithreading in my Windows Forms application.