A Counter object increments the form's Value variable and displays the result in the form's txtResults TextBox.
The Run method enters an infinite loop. It sleeps for 1 second and then uses a SyncLock statement to get a lock on the form. This doesn't do anything to the form, it just means no other thread can lock the form object until we release the lock. To see why this is important, suppose the form's Value variable holds the value 1. Then suppose two threads are running and both enter this section of code at approximately the same time and follow this sequence of events:
- Object 1 increments the form's Value property to 2.
- Object 2 increments the form's Value property to 3.
- Object 1 displays the form's Value property 3.
- Object 2 displays the form's Value property 3.
Instead of displaying the value 2 and then 3, both of the threads display the value 3.
After it locks the form object, the Counter increments Value. It then uses the form's InvokeRequired method to see if the code is running on a Thread other than the one that created the form. If it is (and we know it is in this example), then it cannot access the form's methods directly.
Instead, the program calls the form's Invoke method. This method's first parameter is a delegate indicating the form routine to execute. Its second parameter is an array of parameters to pass to the form routine. In this case, the parameter array contains the text that the DisplayValue method should display.
The object then uses the End SyncLock statement to release its lock. If another thread reaches its SyncLock statement while this object holds a lock on the form, the second object waits until the lock is released.