Results 1 to 28 of 28

Thread: [RESOLVED] Seperating timeControl from GUI Thread using BGW

  1. #1

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Resolved [RESOLVED] Seperating timeControl from GUI Thread using BGW

    I'm currently using a TimeControl Sub that is run on the GUI thread (.i.e. this Sub is called from a Menu.Click routine)
    Code:
    Public Sub TimeControl
       Static LastSimTime As Integer = Enviroment.TickCount
       Dim ActualTime As Integer
       Try
          ActualTime = Enviroment.TickCount
          If LastSimTime + StepIntervall >= ActualTime Then
             Simulation 'This Sub that starts all the BackGroundWorkers(BGW) that do the calculation of movements       
             LastSimTime = ActualTime
          End If
          If StartStop = True Then
             ExecuteAfterPause(StepIntervall, New MethodInvoker( Adressof TimeControl) ' This Sub calls itself as long as StartStop is True
          End If
       Catch ex As Exeption
          '.....
       End Try
    End Sub
    Using it that way the simulation works and is displayed by the GUI.
    However sole GUI actions (like measurment of distance) migth delay the TimeControl. For that reason I would like to use another BGW.
    In the Menu.Click this BGW is just started as "BGW.RunWorkerAsync()" and the TimeControl Sub is called in the BGW_DoWork Sub.
    Using it that way the GUI is only updated when moving the mouse. I even tried to put "MainForm.BGW.ReportProgress(1)" in the TimeControl and
    Code:
    Private Sub BGW_ProgressChanged....
       Me.Update
    End Sub
    (with BGW.WorkerReportsProgress = True)
    with no change.
    In my understanding the .ProgressChanged is handeld on the GUI threat, therefore I did expect the Me.Update the show the actual data as does the movement of the mouse.
    Where am I wrong????
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: Seperating timeControl from GUI Thread using BGW

    Try Me.Refresh, but only for information. Me.Update causes the form to redraw invalid regions using Invalidate. That doesn't mean that they WILL be redrawn, it only queues them up so that the UI can redraw when it gets around to it. Refresh forces an immediate re-draw. It's a bit nasty, in this case, because it will cause the entire form to redraw, which may well be more work than you'd really like it to do. If there is just one or two controls to redraw, then call the .Refresh method for those controls, which will reduce the total drawing.

    However, if this DOES work, then there is something else going on. Assuming that those BGW events are happening at reasonable intervals (greater than 100ms would be reasonable, though it could also be shorter intervals), then even .Invalidate should work. So, if .Refresh works, then change it to .Invalidate and try that. You then get these outcome alternatives:

    1) .Invalidate works, but .Update doesn't: For whatever reason, none of the controls has become invalidated, so the form saw no reason to repaint anything as a result of .Update.

    2) .Refresh works, but .Invalidate doesn't: The UI thread is not processing messages. This can only happen if your loop is causing the UI thread to be constantly busy without giving it a chance to pump the message queue. This seems possible because you appear to be running a de facto busy loop in the TimeControl method. It looks like you are calling a method in an infinite loop. You want to take a look at the stack in this case, too, because it seems like it should be filling up steadily.

    3) None of them work: See #2. After all, the ReportProgress event is just another message that gets added to the message queue, so if you aren't letting the UI process messages, it won't process this one, either.
    My usual boring signature: Nothing

  3. #3

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: Seperating timeControl from GUI Thread using BGW

    Thank you for taking the time for such an elaborate answer.
    Me.Refresh doesn't work either.

    Some further remarks on your answer:
    -Busy Loop-
    The "ExecuteAfterPause" is using the "Pauser" code posted by jmcilhinney http://www.vbforums.com/showthread.p...e-to-Your-Code and further dicussed by dday9 http://www.vbforums.com/showthread.p...ameloop+pauser. In other words, AFAIK this is not a busy loop. I had that code (without the BGW for time) running for houres without any Stack-Error.

    -Nothing gets Invalidated-
    I do use .Invalidate(Region) for all changes on the main picturebox. All the other BGWs just do calculate positions and do invalidate the old and new region. All the drawing is done in the respective .Paint event.

    -The UI thread is not processing messages
    Why would the controls on the UI be updated when moving the mouse? More excatly, when moving the mouse on the main picturebox, this picturebox gets updated,the controls that get changed within the MouseMove routine get updated AND controls which are NOT called in that routine get updated. (The sole exception to that would be pictureboxes within UserControls that don't get their drawing update, but for them I'm using "Marshal.WriteByte (...." the write directly into the memory of the controls Bitmap).
    The code inside the MouseMove just calculates distance-variables (which are drawn in the. Paint event), .Invalidates the regions for them and does some updates of other textboxes.
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: Seperating timeControl from GUI Thread using BGW

    Ok, I see that it is not a busy loop, which is good.

    The odd behavior of the mouse had me puzzled anyways. What is it about moving the mouse that would cause other things to refresh? It was acting as if the messagequeue wasn't pumping messages until the mouse message came along. That doesn't make much sense, but .Refresh would have worked had that been some form of the actual situation.

    If .Refresh isn't working, but .Refresh is being called, then it would appear that at the time that .Refresh is called, there isn't anything new to show. After all, if .Refresh is being called, then the display is showing what it thinks is the current data. You feel that it is showing the wrong thing, obviously, so why is that? Either the data is wrong or your expectations are, and that's going to be tricky to figure out.

    One thing: Since you have a ProgressChanged event with something in it, can you verify that it is being raised at reasonable intervals? The simplest check would be to put a breakpoint in the event, but that would only show one event. An alternative might be to add a List(of date) and write Date.Now to the list in the event handler, then run it for a bit, then pause and check the list to see whether stuff is being written. That might provide some kind of a clue.
    My usual boring signature: Nothing

  5. #5

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: Seperating timeControl from GUI Thread using BGW

    Quote Originally Posted by Shaggy Hiker View Post
    You feel that it is showing the wrong thing, obviously, so why is that? Either the data is wrong or your expectations are, and that's going to be tricky to figure out.
    My expectations are
    -TimeDisplay(TextBox) is showing increasing time
    -PositionDisplay(Textbox) is showing actual postion of MainObject (simulated aircraft)
    -Movement of MainObject is shown on the map

    Without movement of mouse no update on all of them, with movement they update to current data.

    The logging test showed the ProgressChanged being called several times each second, since to FPS is set to 10 and I see it being called up to 10 times, that looks as expected to me.
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  6. #6

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: Seperating timeControl from GUI Thread using BGW

    Further testing, although the ProgressChanged is being called for each frame, the PictureBox.Paint isn't called if the mouse isn't moving within that picturebox.
    The picturebox is invalidated during each frame at least for the movement of the MainObject
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  7. #7
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: Seperating timeControl from GUI Thread using BGW

    Refresh would force that Paint, yet you said that Refresh didn't solve anything. It is kind of acting like the ReportProgress isn't happening on the UI thread. You could probably test that by storing the SynchronizationContext before starting the BGW, then checking against the current SynchContext in the ReportProgress event.

    As you might have figured, I'm guessing here. I'm not sure what's going on, though you do seem to be narrowing in on an answer.
    My usual boring signature: Nothing

  8. #8
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,401

    Re: Seperating timeControl from GUI Thread using BGW

    Are you sure the BGW is the right tool for the job?. The BGW should do some task, report any progress needed then end. I'm actually quite interested in what you are doing. I'm curious to know about the use of MethodInvoker with the BGW, have you actually printed what thread ID your working on? I don't think you should be swallowing exception when unknown problems happen.
    My Github - 1d3nt

  9. #9

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: Seperating timeControl from GUI Thread using BGW

    Am I sure that the BGW is the rigth tool? NO I'm not, that the reason for calling!

    I'm running a game-type application. It can create own objects and recieve objects from elsewhere, all objects are moved (locally using their reported velocities and by update messages) and the MainObject can show all objects in different views (i.e. sensors like radar etc.).
    It's all running based on time. More explanation needed?

    The MethodInovker is used to create a manged GameLoop (as suggested by dday9 in the above mentitoned thread).

    Since I never used SynchronizationContext, I have to do some more reading on that before i'm able to do checks in here.
    Firstly I'll trsy the suggestion to log the thread-ID, which I haven't done yet.

    @Shaggy Hiker. It's not only you who is guessing. Being in the guessing state is the reason for this threat. Thanks for helping out.
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  10. #10

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: Seperating timeControl from GUI Thread using BGW

    @Ident

    The check for ThreadID did show the problem. The ThreadID where I'm calling the BGW.RunWorkerAsync() is not the same as the ThreadID where the BGW is coming back with its .ProgressChanged. But WHY? In humble understanding you call a BGW from the UI thread, let it run on a different thread and it will come back to the UI thread with .ProgressChanged and .Completed.

    BTW: I'm not "swallowing exception", I just didn't edit the Error-Logging code in the thread. And no, there was no error logged for that problem.
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  11. #11

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: Seperating timeControl from GUI Thread using BGW

    I found the problem, it is caused by the recursive GameLoop!
    I did logg the ThreadIDs when calling the BGW (ID 1), in .ProgressChanged Event (ID 2) and in the RunWorkerCompleted Event (Id 1!).
    And the RunWorkerCompleted Event is ONLY being raised after the first .ProgressChanged Event.

    Why would the .ProgressChanged be on another ThreadID??
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  12. #12
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: Seperating timeControl from GUI Thread using BGW

    What is the thread ID for the BGW itself (the background thread)? Is it 2, or is it 3? In other words, is the ProgressChanged event being raised on the same thread as the background process, or is it being raised on yet another thread?
    My usual boring signature: Nothing

  13. #13

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: Seperating timeControl from GUI Thread using BGW

    Only the RunWorkerCompleted is run on the GUI thread (This one I do NOT need!)!
    The ProgressChanged is run the the same Thread where the TimeControl is run, which is not the GUI thread, more exactly each time the TimeControl is run once the ProgressChanged is run on the same ThreadID, in the next run they have a different ThreadID.
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  14. #14
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,401

    Re: Seperating timeControl from GUI Thread using BGW

    Are you sure TimeControl is not being run on the UI making it look like the controls are not updating though.
    My Github - 1d3nt

  15. #15

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: Seperating timeControl from GUI Thread using BGW

    Since the logging showed different .ManagedThreadIDs for the GUI and the TimeControl I am sure.
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  16. #16

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: Seperating timeControl from GUI Thread using BGW

    The main problem was in the usage of the Default instance of the GUI when calling the .ReportProgress. Solving that I got the ProgressChanged run on the GUI thread.
    However, the usage of the recursive GameLoop resulted in multiple uses of the BGW that had already been completed on the first run, which in turn raised an error (I had to change the MethodInvoker into a Deleagate in ordr to accept the BackGroundworker as an argument).

    My options are now:
    -A- Let the TimeControl run without a BGW on the GUI threat (no busy loop used)
    -B- Run the TimeControl on a BGW and use as busy loop in the GameLoop( which would make to purpose of using another thread obsolete)
    -C- Try to "encapsulate" the current GameLoop in a way that the BGW would not be completed (presently no idea, still thinking.....)

    Thanks to both of you for your help.
    I'll close this one.
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  17. #17
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: [RESOLVED] Seperating timeControl from GUI Thread using BGW

    I was never clear on why dday wanted to have a steady tick in his game loop. Typical game loops try to run as fast as they possibly can. Therefore, they are constant loops that time themselves. The loop might have these steps:

    Do
    GatherInput
    DoLogic
    Move
    Draw
    Loop

    Something like a stopwatch would be used to time each iteration of the loop. The elapsed time would be passed to the methods that needed it, which would progress the scene based on the amount of time since the last iteration. Therefore, if there isn't any input and not much logic, the iteration time might be REALLY fast, like 10ms (resulting in about 100FPS), so the movement would be a very short distance. If the logic was involved, the iteration might be kind of slow, like 50ms (about 20FPS), so the movement for each frame would be larger.
    My usual boring signature: Nothing

  18. #18

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: [RESOLVED] Seperating timeControl from GUI Thread using BGW

    I already have the parts of "GatherInput", "DoLogic" and "Move" seperated in BGW. So far my GameLoop was run on the GUI thread, and it was hampered whenever I did some sole GUI-actions. So I reasoned the GameLoop should be on a different thread.
    Using your technique, the GameLoop would be a "busy loop", but not a "busy wait" since its not waiting at all. To my understanding a "busy loop" shouldn't be used?
    Are you suggesting to use such a "busy loop", or am I misunderstanding?
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  19. #19
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,401

    Re: [RESOLVED] Seperating timeControl from GUI Thread using BGW

    *bangs head, should of spotted MainForm.control. Why is another form/class trying to access a BGW from mainform?
    My Github - 1d3nt

  20. #20
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,401

    Re: [RESOLVED] Seperating timeControl from GUI Thread using BGW

    One other thing, and im sorry if i have missed it but what exactly is being updated? Label?, textbox? *shrug*
    My Github - 1d3nt

  21. #21

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: [RESOLVED] Seperating timeControl from GUI Thread using BGW

    Quote Originally Posted by ident View Post
    *bangs head, should of spotted MainForm.control. Why is another form/class trying to access a BGW from mainform?
    Easy answer, Me.Stupid. But I stopped banging my head. Of course it worked when all the calls to BGW were done from the MainForm thread, but when trying to move the TimeControl into another thread I moved those calls to the other thread as well, which was the BIG mistake I assume.

    "Updated"= Picturebox showing actual positions of objects (like a Map-Display), Textboxes showing actual AlphaNumeric data of selected objects (like Lat/Long of object or Playtime). Why *shrug* ???
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  22. #22
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,401

    Re: [RESOLVED] Seperating timeControl from GUI Thread using BGW

    I didn't want to guess more controls, shrug was not at you. Forgive me if this is old ground i want to just get it clear in my head. Your application runs like this.

    On a secondary thread do something
    update some controls
    wait some time
    then does same task again

    If this is the case then why even use a "busy/non busy" loop?
    My Github - 1d3nt

  23. #23

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: [RESOLVED] Seperating timeControl from GUI Thread using BGW

    I do need "something" that controls the time, which IMHO can be either done by using a Timer (which would be on the GUI thread) or by using some kind of loop.
    Any other suggestion?
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  24. #24
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: [RESOLVED] Seperating timeControl from GUI Thread using BGW

    A timer launching the background thread as a Task? Timers are not particularly precise, but you could use a Stopwatch to measure the true elapsed time and pass that to the Task.

    By the way, default instances of forms are thread specific, which is probably what was causing the original problem. There may be a reason to use default instances and threading, but it's not a great idea.
    My usual boring signature: Nothing

  25. #25
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,401

    Re: [RESOLVED] Seperating timeControl from GUI Thread using BGW

    Why does it need to be done on the UI thread as this seems to be your worry. The forms.timer tick is performed on the UI, why not use System.Timers class thats tick is raised on a secondary thread.
    My Github - 1d3nt

  26. #26
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,401

    Re: [RESOLVED] Seperating timeControl from GUI Thread using BGW

    Quote Originally Posted by Shaggy Hiker View Post
    Timers are not particularly precise,
    Agreed but at best iv only noticed it as a second out after a long time. As far as i know it only calls WM_TIMER message which is simply a message and not high priority. Threaded timers are more accurate. "off top my head comments"
    My Github - 1d3nt

  27. #27

    Thread Starter
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: [RESOLVED] Seperating timeControl from GUI Thread using BGW

    System.Timers, each day something new to me.
    I'll look into that one, Thanks again.

    @Shaggy Hiker: YES, the default instance was the original problem!(post #16)
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  28. #28
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: [RESOLVED] Seperating timeControl from GUI Thread using BGW

    I thought you had figured that out, but it wasn't clear from the post whether you had recognized that it's a characteristic of default instances or not. It's really a rather weird aspect of them, and one that I often forget about. Nasty little oddity, really.

    I believe that the code JMC posted in that link is using a System.Timers.Timer.
    My usual boring signature: Nothing

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width