locked
How do I slow down program execution RRS feed

  • Question

  • Hi

     

    Using movong blocks on the screen to show the difference between different sort algorithms.

    Running each sort in its own thread with BackgroundWorker.

    Of course, the program executes so quickly that one cannot see anything happening.

    I have tried putting in a for next loop each time values are swapped in the arrays,

    but this is not really acceptable.

     

    Is there any way I can make the app run slowly after I click on Sort, and then go back to normal

    when all 3 sorts are completed?

     

    Thanks,

    Nigel

     

    Thursday, March 27, 2008 7:28 AM

Answers

  •  

    Hi,

    I wonder if I could perhaps present a different maybe more Object Oriented solution for the problem.

     

    I understand from reading the original post that the problem space is as follows:-

     

    •  Different sort algorithms are to be executed each on its own thread.
    •  Ideally each sort algorithm should execute as fast as possible (to demonstrate how each one works)
    •  A visual representation of how each sort algorithm works needs to be presented to a target user.
    •  That visual representation needs to operate in user time, not system time.

     

    The decouple is that the sort algorthms do not work in user time which is desired.

     

    My solution would be to decouple the execution of the algorithms from the presentation of the animation to the users.

     

    To do this perhaps a method would be to execute the sort algorithms prior to displaying anything to a user. Take a timing of each individual threads Execution Time and multiply it by a constant value (the Scale value).  The resultant number will be for each thread its execution period represented in User Time.

     

    Now just create an animation that uses each threads User Time to represent itself to the user.  The result is that the user will be able to see whats happening - what they see is a proportional representation of a real time scenario.

     

    So, if sort routine one takes 5ms to execute and sort routine two takes 30ms to execute, then if you use a scalar value of 1000ms (1s), the first animation routine will complete in 5 seconds and the second animation routine will complete in 30 seconds which is visually enough time for the user to get the point (there shouldnt be such a deviation in real life, I am just making an example).  Executing the sorts before hand in this scenario would not add much delay time (30ms max). 

     

    For longer sorts, there is a slightly different technique that is used which involves some user pre-emption.

     

     

    Thursday, March 27, 2008 9:01 PM

All replies

  • Hi Nigel,

     

    Pretty interesting problem! Smile

    Usually people are curious how to increase speed of application.

     

    You can use System.Threading.Thread.Sleep(int miliseconds) methods to wait a bit after each block moving.

     

    Thursday, March 27, 2008 7:40 AM
  • Thread.Sleep will help as Vitaliy suggested, but I suspect that, it will cause some differences in the actual timing of the algorithms.

     

    You may have to look at using really large arrays so that there is some computing time involved and possibly do some screen updates or disk IO.. such operations are slower them in memory data manipulation operations !

     

    Thursday, March 27, 2008 8:40 AM
  • I will need to load quite a few files to slow things down enoug!!! Not very elegant, either. It

    is bad enough that I am using coloured panels of different sizes to show "blocks being sorted."

     

    Can't user a timer to make the threads sleep because I am using BackgroundWorkers

    and can't make them sleep. Or can I?

     

    Large arrays won't help because I want to update the screen every time 2 elements are swapped.

    It's bad enough that with the shell sort I have to show the contents of temp as well as the array.

     

    It looks as though I will have to go back to threads with delegates to inform the screen to update,

    with timer regularly putting them all to sleep.

    Thursday, March 27, 2008 10:16 AM
  • Here's a stupid, stupid, stupid response.

     

    In ye old days, long ago, when you needed to call one process, and wait for it to finish something, or another process to have interacted, ...  What was done was this:

    Have your main app write a textfile C:\tmp\stage.txt . and write a 0 in it.  Start three processes and have them wait for a 1.

    Have your main app (perhaps with a timer) write a 1 in it, then a 2, then a 3, then close....

     

    Of course this is all byegones now (thankfully)!

     

    But maybe this stupid stupid stupid idea can still work.  Have a public static class with one static property in it (an int).

     

    Then have your main program update the int, meaning till what stage can the backgroundworkers do their job?  Then just put some infinite loops in your backgroundworkers => while(staticClass.Stage != 3) {Threat.Sleep(100);} will have your code hanging there till staticClass.Stage is 3.

    Make sure you have some way to get out of it though if something still goes wrong hehe...

    Thursday, March 27, 2008 10:32 AM
  • Nice idea.

     

    Set a timer to count up, reverting to 0 when reaching 2000.

    Put while loop in sort routines waiting for count to reach 1999.

    Set timer delay to 1.

    Routines wait until counter reaches 1999 and then finish sorting before

    the next timer tick!!!!

     

    I can use this ruse with threads and delegates, because threads can be put to sleep, whereas

    backgroundworkers cannot.

     

    Sigh, I deleted all my delegate/event code instead of just commenting it out!!

    Thursday, March 27, 2008 11:19 AM
  • Thread.Sleep is inaccurate and wasteful. 

     

    Ideally you should determine the criteria for how long you want to wait.  If you want to lock step the algorithms so that each one performs a "step" together then I would question why you are using threading at all.  Still, if you want to lockstep the algorithms then create a sync object for each thread (an event works well but a semaphore might be better).  After an algorithm completes a step it blocks on the sync object waiting for the other algorithms to get there as well.  Once they are all there the sync object resets and the algorithms move to the next step.  Of course if all algorithms are so fast that lockstepping still is a blur then you'll need some sort of arbitrary stall.

     

    To arbitrarily, and efficiently, stall a thread for a fixed period of time you can use a wait object.  Any object will do provided it derives from WaitHandle.  An event is probably easiest or even a mutex.  Wait on the object for the desired interval.  Since it will never be set you'll efficiently wait for the timeout.  Do this at the end of each step and you'll have an arbitrary delay in your code.

     

    An alternative to a wait object is using Thread.SpinWait.  This method (known as a spinlock) actually acts like a for loop in the sense that it'll arbitrarily stall for a given # of iterations.  It is predominantly used to avoid taking a lock for short-lived locking situations but you could use it to add a delay.  The only downside is that the # of iterations won't map to a certain time interval.  A slow machine will delay longer than a fast machine.

     

    Michael Taylor - 3/27/08

    http://p3net.mvps.org

     

     

     

    Thursday, March 27, 2008 1:39 PM
  • Michael - thanks, but the whole point is to make the 3 sort algorithms run asynchronously so that one can see how they differ in methods and especially speed. And using BackgroundWorkers there are no Thread.SpinWait and other calls.

     

    I have had an idea for the wait loops - 3 timers and 3 flags, 1 for each algorithm. Flags set to make sort algorithm enter a while forever loop. When an algorithm swaps 2 elements it can call worker.ReportProgress and then hit the while forever loop.

     

    Worker.ProgressChanged can update the screen display, and enable the specific timer. Timer set to trigger every 100ms. Timer counts to, say, 7 loops (700ms), which is enough for the user to perceive the screen changes, disables itself and clear the flag so that the sort algorithm steps on. The sort algorithm then immediately sets the flag again so that the next time it swaps 2 elements it will hit the while forever loop again.

     

    The number of loops can be adjusted if 700ms is too short or too long.

     

    This should work, and it puts no speed penalties on the other algorithms as it does not waste time doing a for next loop 300000000 times.

     

    And they will all run at their own speeds, stopping in effect just long enough for the user to see elements being swapped. And the number of times elements are swapped are important attributes of the various sort algortithms.

     

    Will have to use something other than quick-sort - because of recursion, with initial values in the call, it cannot call backgroundworker.

     

    Thursday, March 27, 2008 2:29 PM
  •  Nigel Mackay wrote:

    Michael - thanks,

     

    i am intimidate by Michael Taylor to whom I once said I owe a good chunk of my present knowledge base, however, I want to throw in my incompetent (but supperted by experience) opinion on the threads. perhaps it will help you to solve your problem.

     

    i used to use BackGroundWorker. Actually one of my major app still runs it efficiently and I am afraid to tinker with it but I will never do it again. I have developed a simple method that so far has never got me in trouble in very sensitive situations actually. See how I can do it.

     

    A new thread is defined as:

     

    ThreadStart threadStart = new ThreadStart ( createPipeServer );

    Thread trd = new Thread ( threadStart );

    trd.Name = "pipeServer2";

    trd.IsBackground = true;

    Globals.generListThreads.Add ( trd );

    trd.Start ( );

     

    The delegate:

    private void createPipeServer ( )

    {

    PipeServer2.SendMessageToClient ( "" );

    } // createPipeServer

     

    then globally (out of the nameswpace, or if you want at the class level you define a List that will hold all your threads with their names:

     

    List<Thread> genListOfThreads = new List<Thread> ( );

     

    That first piece of code is actually in a Click event delegate. You can catch your threads at any time by going thru your list:

     

    forarch (Thread trd in Globals.genListOfthreads)

    {

    if (trd.Name == "whatYouwantTocatch")

    {

    // put your  thread to sleep of wake it up or whatnot

     

    }

    }

     

    I think it is much ado about nothing.

     

    Yesterday I downloaded a set of samples for VS2008 (C# samples + Linq samples). Among C# Language samples there are 3 progects (under one solution) on threads. ThreadPool, ThreadSync, and something else. You can look into those also. The threads are set up differently. they do not use ThreadStart class I believe but they do it without background worker. I found it interesting but my threads are doing fine and unless .... .

Thursday, March 27, 2008 2:57 PM
  • Have you considered letting the sort routines run as is, and queuing the actions they took into different queues?

    Then you can let the UI play back the data from the action queues at whatever speed you want. There doesn’t seem to be any reason that your UI needs to be synchronized with the sorts themselves, you just need to know what the sort did and when it did it.

     

    Thursday, March 27, 2008 3:11 PM
  • One more idea. I am not sure it is going to work but you can give it a thought. If there is a control defined in a thread, then you can try to catch the moment the thread is amanable to manipulations with a MethodInvoker and put it to sleep like this (this is just to set up the Text property for a control):

     

    public static void SetControlText ( System.Windows.Forms.Control clr, String text )

    {

    if ( clr.InvokeRequired )

    {

    clr.BeginInvoke ( ( MethodInvoker )delegate ( )

    {

    SetControlText ( clr, text );

    } );

    }

    else

    {

    clr.Text = text;

    }

    } // SetControlText

     

    This way you can keep your bakground worker the way it is.

    Thursday, March 27, 2008 3:20 PM
  • Nigel, the various threading calls are available irrelevant of whether you're using BWC or not.  BWC uses a thread pool thread under the hood.  Calling Thread.SpinWait within the DoWork handler will causes the BWC thread to spin wait.  The wait object suggestion works irrelevant of threading as well.

     

    The problem you are going to have with creating an arbitrary for loop is that the optimizer in release mode will remove it since it won't do anything of interest.  You can muck around with it to get it to interact in some way to make the optimizer not remove it but why bother wasting the time when there are better solutions.  IMHO.

     

    Michael Taylor - 3/27/08

    http://p3net.mvps.org

     

     

     

    Thursday, March 27, 2008 3:29 PM
  •  TaylorMichaelL wrote:

    Nigel, the various threading calls are available irrelevant of whether you're using BWC or not.  BWC uses a thread pool thread under the hood.  Calling Thread.SpinWait within the DoWork handler will causes the BWC thread to spin wait.  The wait object suggestion works irrelevant of threading as well.

     

    The problem you are going to have with creating an arbitrary for loop is that the optimizer in release mode will remove it since it won't do anything of interest.  You can muck around with it to get it to interact in some way to make the optimizer not remove it but why bother wasting the time when there are better solutions.  IMHO.

     

    Michael Taylor - 3/27/08

    http://p3net.mvps.org

     

    Michael hi,

     

    Your post clicked a bell and now I have a question to ask. I am wondering if the behavior I obesrve in one of my app is related to what you called the optimizer in release mode. The application I am talking about has at its core a TreeView that controls my entire databases There are perhaps two dozen databases with various tables in them. The TreeView nodes are filled on demand. Periodically I do a search of some items in various tables. Then I read the text in memo (text) fields.

     

    If considerable time elapses between two searches the next search eventually fails. I get an exception at ExecuteNonQuery ( ) statement. The tables are OleDb (VFP) not Sql Server's. I use

     

    using (OleDbConnection conn = new OleDbConnection (..

    {

    }

     

    configuration. My tactic so far has been to close the app and restart it. Today I noticed the following: If after a failure I do search in a different table, the connection to the same DB succeeds, I get the results of the search back into the app. After that I can go back to do a search in the same table that just failed a minute ago and it will proceed as normal!!!

     

    What is it all about? Is there a way to improve it?

    Thursday, March 27, 2008 8:08 PM
  • I doubt it is the optimizer as it would impact all runs of the code (it is only JITted once after all).  Optimization occurs when you compile your code (in release mode) and potentially when it is JITted.  Either case though it'll impact all runs of the code.

     

    Sounds like maybe the connection is being closed after a given timeout.  It really depends upon whether you keep connections open or whatnot.  I'd recommend posting the issue in the forums along with some info on how you manage the connection and what exception you are getting.  An exception in Execute... implies that you've already opened the connection so a timeout is unlikely.  When you create the post be sure to provide us with the exception information so we can track down what is going on.

     

    Michael Taylor - 3/27/08

    http://p3net.mvps.org

     

     

    Thursday, March 27, 2008 8:51 PM
  •  

    Hi,

    I wonder if I could perhaps present a different maybe more Object Oriented solution for the problem.

     

    I understand from reading the original post that the problem space is as follows:-

     

    •  Different sort algorithms are to be executed each on its own thread.
    •  Ideally each sort algorithm should execute as fast as possible (to demonstrate how each one works)
    •  A visual representation of how each sort algorithm works needs to be presented to a target user.
    •  That visual representation needs to operate in user time, not system time.

     

    The decouple is that the sort algorthms do not work in user time which is desired.

     

    My solution would be to decouple the execution of the algorithms from the presentation of the animation to the users.

     

    To do this perhaps a method would be to execute the sort algorithms prior to displaying anything to a user. Take a timing of each individual threads Execution Time and multiply it by a constant value (the Scale value).  The resultant number will be for each thread its execution period represented in User Time.

     

    Now just create an animation that uses each threads User Time to represent itself to the user.  The result is that the user will be able to see whats happening - what they see is a proportional representation of a real time scenario.

     

    So, if sort routine one takes 5ms to execute and sort routine two takes 30ms to execute, then if you use a scalar value of 1000ms (1s), the first animation routine will complete in 5 seconds and the second animation routine will complete in 30 seconds which is visually enough time for the user to get the point (there shouldnt be such a deviation in real life, I am just making an example).  Executing the sorts before hand in this scenario would not add much delay time (30ms max). 

     

    For longer sorts, there is a slightly different technique that is used which involves some user pre-emption.

     

     

    Thursday, March 27, 2008 9:01 PM
  • Thanks everyone

     

    I tried the timer, flag and while loop method. This works in so much as when one routine ends it does not significantly affect the speed of the other routines.

     

    However, because a bubble sort only needs 1 wait loop per element swap, to show what is going on with a shell sort (the temp contents), it requires 3 waits. This makes the shell sort slower than the bubble sort!!!

     

    It seems that the best solution is AndyW's. 

     

    I can still use OOP for displaying the 3 "movies" of the progress of each sort, and so get my hand in with inheritance and overrides.

     

    The user will never detect it, it will show the way the different algorithms work, and their speed differences.

     

    This way even the quick sort can be demo'd.

     

    Makes me think I should have chosen something else as a starter app!! At least it will achieve one of my objectives - when my mother visits in a few weeks I can make her understand what I mean when I say "I wrote a program which does such and such"!!! She has no idea what I mean.

     

    As for slowing a program down in general, suitably placed Thread.SpinWait's would work just fine.

     

    Thanks again, everyone.

     

    Friday, March 28, 2008 4:27 AM
  •  TaylorMichaelL wrote:

    I doubt it is the optimizer as it would impact all runs of the code (it is only JITted once after all).  Optimization occurs when you compile your code (in release mode) and potentially when it is JITted.  Either case though it'll impact all runs of the code.

     

    Sounds like maybe the connection is being closed after a given timeout.  It really depends upon whether you keep connections open or whatnot.  I'd recommend posting the issue in the forums along with some info on how you manage the connection and what exception you are getting.  An exception in Execute... implies that you've already opened the connection so a timeout is unlikely.  When you create the post be sure to provide us with the exception information so we can track down what is going on.

     

    Michael Taylor - 3/27/08

    http://p3net.mvps.org

     

     

     

    ALL my connections are immediately closed. I could not do otherwise. There are multiple places in the app where I tap the Dbs and without closing them meticulously I began running in trouble at a very early stage.

     

    I will post the exception code but I found a nice, practicaly wrokaround. I catch the exception in try catch block, the routine returns null object (Dictionary).and the calling routine immediately queries a different table in the same DB, gets an empty string because the key for the query is purposely set to nonsense and then calls the original table which just failed.

     

    Now, this last part does not really work immediately because of improper threading, i assume, so the next call is not really executed BUT I get an audible statement thru TextToSpeech SAPI which says: "Please repeat the click." I click the same button again and BINGO, it works! the query to the table that failed a minute ago now brings a result.

     

    It is explicitly weird but in a sense it is a nice practical compromise. Of course I want to get down to the bottom of it because such things may happen elsewhere. I will post the exception.

     

    Thanks.

    Saturday, March 29, 2008 1:03 AM
  •  TaylorMichaelL wrote:

    I doubt it is the optimizer as it would impact all runs of the code (it is only JITted once after all).  Optimization occurs when you compile your code (in release mode) and potentially when it is JITted.  Either case though it'll impact all runs of the code.

     

    Sounds like maybe the connection is being closed after a given timeout.  It really depends upon whether you keep connections open or whatnot.  I'd recommend posting the issue in the forums along with some info on how you manage the connection and what exception you are getting.  An exception in Execute... implies that you've already opened the connection so a timeout is unlikely.  When you create the post be sure to provide us with the exception information so we can track down what is going on.

     

    Michael Taylor - 3/27/08

    http://p3net.mvps.org

     

    Michael hi,

     

    This is the exception Console output: My workaround does not seem to be effective. For some reason, with elapsed time (about 45 min of inaction) this table cannot get opened, although the connection seems to be OK since I can access a different table right away.

     

    Cannot open file c:\vfp_projects\data\comeandgetdatbase\categories.dbf.
        at System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBPARAMS dbParams, Object& executeResult)
       at System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object& executeResult)
       at System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior behavior, Object& executeResult)
       at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method)
       at System.Data.OleDb.OleDbCommand.ExecuteReader(CommandBehavior behavior)
       at System.Data.OleDb.OleDbCommand.ExecuteReader()
       at ComeAndGet.FillTables.searchForWords(String cAlias, String wordToFind, Boolean& success) in C:\VCsharp_Projects\ComeAndGet\ComeAndGet\FillTables.cs:line 382

    Monday, March 31, 2008 12:49 AM
  • Alex, can you move your discussion to a separate post?  It is OT for this particular post.  I suspect it might require more than a simple response to get resolved so I'd rather not mix it up with this post since I don't think it is related to slowing down the execution.  Thanks.

     

    Michael Taylor - 3/31/08

    http://p3net.mvps.org

     

    Monday, March 31, 2008 12:18 PM