I am trying to keep my GUI thread responsive during long operations. These operations must be synchronous, since they are usually operations that must be performed before the requested operation is completed.
I tried to do this with a background worker, monitors, and a lock object. Essentially, I want to start a timer before starting a lengthy process, start a lengthy process in the background thread, and wait for the background thread to mean that it has finished before continuing with the dependent code. If the long process takes too much time, show the "loading ..." dialog to the user so that they know that the application has not crashed.
An example of this is the “User Clicks” button in a graphics package, loading a large image from the disk must occur before we can draw the image, and then print pi, calculated for millions of decimal places at the top.
I can’t make the loading of the image from the disk asynchronous, which would respond to the user interface, since the user could initiate another operation that ruined the state of the program (i.e., the cancel operation).
I could just change the cursor to an hourglass and do with it, but in some cases I want the user to be able to cancel the operation too - the "Loading ..." dialog with the cancel button will take care of this pretty well.
For what I initially wanted, the locking object and System.Threading.Monitor.Enter() were involved, so that the user interface thread waited for the long thread to finish, and it continues to run. If the timer fires before the end of the long thread, then the user interface thread is still available to handle the event and draw a dialog box on the screen.
The problem I am facing is that I cannot get the Background Worker to lock the object before the UI thread tries to get the lock.
Quite annoyingly, I use some kind of third-party code, which is a very black box for processing. Therefore, I can’t adapt the code for thread-friendliness and report on its progress or support for cancellation.
My question
Is there a proven way to port third-party code so that the UI thread remains responsive, and can I show the cancel dialog if necessary? - There will be several cases when long work ends almost instantly and does not require a dialog box to be displayed.
Small clarification
Why do I want to do this? Asynchronous operations are a favorite type of Windows application ...
Well, I don’t want to block every aspect of the user interface when multiple async runs, and then unlock every aspect when it is finished. I could either set the cursor or physically disable all the baptions, etc. Etc., But really, I would prefer to simply wrap the call in "some object / method, etc.", which will allow the dialog to pop up if (and only if) the operation takes a lot of time to affect the user. I would not have to worry about changes in the thread of execution, anyway (as a whole) I could support atomic operations in the code (not split into callbacks) and still have a “responsive” user interface.
I can understand why I still have not succeeded in creating a BackgroundWorker / Thread in a synchronous lock thread, but I'm worried that I will have to go along the while(true){ sleep() } track in the GUI thread than using locks.