Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Threading & Locks & Waiting

I am attempting to make my GUI thread remain responsive-ish during long running operations. These operations must be synchronous as they are usually operations which are required to finish before the requested operation can complete.

I was attempting to do this with a background worker, monitors and a lock object. Essentially I want to start a timer before the long running process is started, start the long running process in the background thread and wait on the background worker thread to signify that it has finished before continuing with the dependant code. If the long running process takes too long then show a 'loading...' dialogue to the user so they are aware the app has not crashed.

An example of this might be User clicks button in graphics package, loading of a large image from disk must happen before we can draw the image then print pi calculated to a million decimal places over the top.

I cannot make the loading of the image from disk asynchronous which would keep the UI responsive as the user could initiate another operation which messes up the program state (i.e. an undo operation).

I could simply change the cursor to be an hourglass and be done with it, but in a number of instances I want the user to be able to cancel the operation too - a "Loading..." dialogue with a cancel button would take care of this quite well.


What I was aiming for originally was using a lock object and System.Threading.Monitor.Enter() so that the UI thread waits until the long running thread has finished, then it continues executing. If the timer fires before the long running thread has completed then the UI thread is still available to handle the event and draw the dialogue box on the screen.

The issue I am encountering is that I cannot get the Background worker to lock the object before the UI thread attempts to get a lock.

Rather annoyingly I am using some 3rd party code which is very black box to do processing. Hence I can't tailor the code to be thread friendly and report its progress or support cancelling.


My Question

Is there any proven way wrapping 3rd party code so that the UI thread remains responsive and I can show a cancel dialogue if need be? - There will be a number of instances where the long running operation completes almost instantly and doesn't require a dialog to be shown.


A little futher clarification

Why do I want to do this? Asynchronous operations are the darling of windows applications...

Well I don't want to have to lock down every aspect of the user interface when a long running async operation is started, then unlock every aspect when it has finished. I could - either by setting the cursor or physically disabling all the buttions etc etc, but realistically I'd prefer to be able to simply wrap the call in 'some object/method etc' which will allow a dialog to popup up if (and only if) the operation is taking long enough to impact on the user. I'd not have to worry about changes to the flow of execution, I'd still (on the whole) be able to maintain atomic operations in code (not split across callbacks) and still have a 'responsive' UI.

I can understand why I've been unsuccessful so far in crafting a BackgroundWorker / Thread into a synchronous blocking thread, but I do worry that I'm going to have to go down the while(true){ sleep() } route in the GUI thread rather than using locks.

like image 474
Ash Avatar asked Jan 23 '23 13:01

Ash


1 Answers

Before you get any further I would seriously consider the BackgroundWorker class in .NET. You said you used a "background worker", so I am not sure if that is what you meant. It has facilities for calling back to your UI with progress notifications from within your worker function. With the progress notifications, it should significantly cut down on your need for synchronization objects.

like image 110
Mike Marshall Avatar answered Jan 26 '23 00:01

Mike Marshall