Resolved Looking for a suitable example of threaded windows forms app

SilverShaded

Well-known member
Joined
Mar 7, 2020
Messages
93
Programming Experience
10+
Hi im looking for some guidance/example of a windows forms app which has the follwing featrures:

An independant solver engine
Seperate winforms interface
The solver engine sends information back to be displayed in the interface periodically
The interface is used to configure the solver engine

I had something working but not reliably, if the interface was re-configured while the sover engine was running it caused conflicts
Just after any hints or example anyone might be able to point me to as threaded programming is new for me.
 
Solution
then transfer the results back to the original flowsheet
If it's simpler to swap out the starting flowsheet for the solved one then you could make it an output of the BGW's work (the runworkercompleted event has an args with a Result property, and the event is also fired on the UI thread for ease of updating controls with the result. If it were as simple as "bind the flow chart display control to a new flow sheet" then the runworkercompleted could perhaps do that binding which would update the UI)

Progress might be a bit more difficult - do you have access to change the code that makes the progress? Can you insert a regular event emit (for exampel) to say that 10%, 20% 30% etc is now done? If so you can capture those events in...
Look at the various code examples for BackgroundWorker.
 
Look at the various code examples for BackgroundWorker.
Hi Thanks, I had it "workimg" with backgroundworker, the problem i had was if i click certian interface dialogs it tires to update the solver engine configuration.

I guess what i want is to freeze the solverengine configuration and prevent this happening until at least its finished solving.
I am a bit confused about the lock statement as i thought this is whats it should do

So i thought the follwing code would lock the Flowsheet until it finished solving, but it doesnt seem to be doing that in so much that clicking on the interface can still prevent the solver solving properly.

C#:
lock (GlobalModel.Flowsheet)
 {
      GlobalModel.Flowsheet.PreSolve();
 }
 
lock prevents another thread from running line 3 until the first thread is done executing line 3.
 
Does that imply it locks everything that line three calls, ie the entire solver engine?
No, it just means another thread can't enter that lock and execute line 3 until the first thread is finished performing that call and exits the lock.
 
Again, please look at the BackgroundWorker. The sample code Microsoft provides shows them disabling some controls on the UI while the background worker is running.
 
Last edited:
RunWorkwrAsync takes a parameter object that you can use to pass the inputs. You should aim to pass an object (like your flowsheet) that is built entirely in the code the makes the background worker go, and that builder code doesn't run if the worker is already busy

C#:
GoButton_Click(..){
  if(bgw.IsBusy) return;

  var f = new FlowSheet();
  f.Thing = thingTextBox.Text;
  ...
  bgw.RunWorkerAsync(f);
}

Ergo you're passing all the state the bgw need to work into the worker rather than it getting it from some shared place that other controls can edit. It's naturally isolated unless internally to a FlowSheet it uses static stuff (ugh)

To report progress or update controls from within DoWork set ReportsProgress true on the bgw and fire the ProgressChanged event. You don't have to give a real percentage progress. The passes int can be any value interpreted in any way in the progress changed handler
 
Last edited:
Again, please look at the BackgroundWorker. The sample code Microsoft provides shows them disabling some controls on the UI while the background worker is running.
I appreciate the help you often provide, in this case the MS examples are just far too simplistic and enable/disable controls which is not what i want to do. For example various tabs (including the visual designer tab) on the "ColumnDLG" sub-flowsheet are checking and rewriting the solver engine configuration on the fly as they are modified, the solver is not necessarily run from the sub-flowsheet but is run from anywhere automatically when any input variable is changed. So when run its would have to somehow disable the relevant routines in the Interface (and many other places, as the user can attempt to modify any object) which is just far to messy and problematic to handle. Probably i need to restructure the program which is a biggish job so was looking for any and all possible alternative ways of doing things before committing to make the changes.
Full.jpg
 
RunWorkwrAsync takes a parameter object that you can use to pass the inputs. You should aim to pass an object (like your flowsheet) that is built entirely in the code the makes the background worker go, and that builder code doesn't run if the worker is already busy

C#:
GoButton_Click(..){
  if(bgw.IsBusy) return;

  var f = new FlowSheet();
  f.Thing = thingTextBox.Text;
  ...
  bgw.RunWorkerAsync(f);
}

Ergo you're passing all the state the bgw need to work into the worker rather than it getting it from some shared place that other controls can edit. It's naturally isolated unless internally to a FlowSheet it uses static stuff (ugh)

To report progress or update controls from within DoWork set ReportsProgress true on the bgw and fire the ProgressChanged event. You don't have to give a real percentage progress. The passes int can be any value interpreted in any way in the progress changed handler
Yes it may be possible to reconfigure the program to do this, i can see how that would solve the problem, I need to think how to re-configure it all, but may be possible without breaking too much of the code.

Actually i think im going to just clone the flowsheet, solve it as per your suggestion, then transfer the results back to the original flowsheet, periodic updates will have to be handled by refreshing the original flowsheet with the partial solution results somehow. At least ill try that, although cloning all the objects osnt that straighforward as there a lot of (stream) connections between objects that need to be handled and other stuff.
 
Last edited:
then transfer the results back to the original flowsheet
If it's simpler to swap out the starting flowsheet for the solved one then you could make it an output of the BGW's work (the runworkercompleted event has an args with a Result property, and the event is also fired on the UI thread for ease of updating controls with the result. If it were as simple as "bind the flow chart display control to a new flow sheet" then the runworkercompleted could perhaps do that binding which would update the UI)

Progress might be a bit more difficult - do you have access to change the code that makes the progress? Can you insert a regular event emit (for exampel) to say that 10%, 20% 30% etc is now done? If so you can capture those events in the DoWork and raise a ProgressChanged on the BGW - again this event runs on the UI thread so you could pass a partially completed flow to whatever visualizer control is showing it
 
Solution
If it's simpler to swap out the starting flowsheet for the solved one then you could make it an output of the BGW's work (the runworkercompleted event has an args with a Result property, and the event is also fired on the UI thread for ease of updating controls with the result. If it were as simple as "bind the flow chart display control to a new flow sheet" then the runworkercompleted could perhaps do that binding which would update the UI)
Possibly. The engine objects contained within the flowsheet are pernanently attached to the graphical objects, the flowsheet is then built up from all of the engine objects before solving and then solved, it might work ok to simply replace the engine objects on each graphical object after the flowsheet solves with the cloned copies, but i'd like that update to take place periodically, so we can see the result of each iteration and which individual objects are solved at any given point in time and if a particular engine object dialog is open to see iteration results etc. Basically make it as interactive as possible.

So im thinking build the flowsheet, clone it, solve it, then update the original objects (or replace with the clones). For each itreration in the solver send back the currently solved object clone (via ProgressChanged event) and continutously update the individual graphical objects data/attached enginemodel. (Or some combination of the above).

Anyway i need to do deep clones of everything which is going to take me a while... :)

Thanks for the pointers, i think its heading in the right direction now.
 
For example various tabs (including the visual designer tab) on the "ColumnDLG" sub-flowsheet are checking and rewriting the solver engine configuration on the fly as they are modified, the solver is not necessarily run from the sub-flowsheet but is run from anywhere automatically when any input variable is changed. So when run its would have to somehow disable the relevant routines in the Interface (and many other places, as the user can attempt to modify any object) which is just far to messy and problematic to handle.
That would suggest that the solver engine is not as independent as you described in your original post.
 
Back
Top Bottom