Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Visual Basic
  4. Refreshing the UI during a long process using VB.NET 3.5 without Application.DoEvents - believe me Ive tried!

Refreshing the UI during a long process using VB.NET 3.5 without Application.DoEvents - believe me Ive tried!

Scheduled Pinned Locked Moved Visual Basic
designcsharpdatabasequestion
4 Posts 3 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Marcus J Smith
    wrote on last edited by
    #1

    I have an application that has a simple user interface but quite a bit of code under the hood. The interface is a file processing form where the user chooses a file and then clicks a button to process the selection. The code disables all buttons on the form and has at it. Quite a bit of the code is reading from the file and I report how many records every 100 count and then call Application.DoEvents (I know this is bad that is why I am here). Part of this application uses BackGroundWorkers to run long SQL queries/updates where I use the .IsBusy property in a while loop and update a time elapsed message then call Application.DoEvents. I have a continuous progress bar that just runs all the time to show that something is happening but not necessarily reporting actual progress. I also have true multi-threading where I kick off threads and I have a few steps in the process where I wait for a few of those threads to complete before starting others, as part of that waiting process I call the Application.DoEvents call again. I have found many many articles online and forums where people say not to use Application.DoEvents, you should use backgroundworkers with ProgressChanged events. Well even though I implemented the Delegate step that they mention to set the value on the status bar for time elapsed, as soon as I take out the Application.DoEvents the form will report that it is not responding and if the user clicks on it they get the typical whited out form. What should I use instead to guarantee that I dont have code stepping on itself?


    CleaKO

    "Now, a man would have opened both gates, driven through and not bothered to close either gate." - Marc Clifton (The Lounge)

    L L 3 Replies Last reply
    0
    • M Marcus J Smith

      I have an application that has a simple user interface but quite a bit of code under the hood. The interface is a file processing form where the user chooses a file and then clicks a button to process the selection. The code disables all buttons on the form and has at it. Quite a bit of the code is reading from the file and I report how many records every 100 count and then call Application.DoEvents (I know this is bad that is why I am here). Part of this application uses BackGroundWorkers to run long SQL queries/updates where I use the .IsBusy property in a while loop and update a time elapsed message then call Application.DoEvents. I have a continuous progress bar that just runs all the time to show that something is happening but not necessarily reporting actual progress. I also have true multi-threading where I kick off threads and I have a few steps in the process where I wait for a few of those threads to complete before starting others, as part of that waiting process I call the Application.DoEvents call again. I have found many many articles online and forums where people say not to use Application.DoEvents, you should use backgroundworkers with ProgressChanged events. Well even though I implemented the Delegate step that they mention to set the value on the status bar for time elapsed, as soon as I take out the Application.DoEvents the form will report that it is not responding and if the user clicks on it they get the typical whited out form. What should I use instead to guarantee that I dont have code stepping on itself?


      CleaKO

      "Now, a man would have opened both gates, driven through and not bothered to close either gate." - Marc Clifton (The Lounge)

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      CleaKO wrote:

      Well even though I implemented the Delegate step that they mention to set the value on the status bar for time elapsed, as soon as I take out the Application.DoEvents the form will report that it is not responding and if the user clicks on it they get the typical whited out form.

      Can you post an example of that loop?

      I are troll :)

      1 Reply Last reply
      0
      • M Marcus J Smith

        I have an application that has a simple user interface but quite a bit of code under the hood. The interface is a file processing form where the user chooses a file and then clicks a button to process the selection. The code disables all buttons on the form and has at it. Quite a bit of the code is reading from the file and I report how many records every 100 count and then call Application.DoEvents (I know this is bad that is why I am here). Part of this application uses BackGroundWorkers to run long SQL queries/updates where I use the .IsBusy property in a while loop and update a time elapsed message then call Application.DoEvents. I have a continuous progress bar that just runs all the time to show that something is happening but not necessarily reporting actual progress. I also have true multi-threading where I kick off threads and I have a few steps in the process where I wait for a few of those threads to complete before starting others, as part of that waiting process I call the Application.DoEvents call again. I have found many many articles online and forums where people say not to use Application.DoEvents, you should use backgroundworkers with ProgressChanged events. Well even though I implemented the Delegate step that they mention to set the value on the status bar for time elapsed, as soon as I take out the Application.DoEvents the form will report that it is not responding and if the user clicks on it they get the typical whited out form. What should I use instead to guarantee that I dont have code stepping on itself?


        CleaKO

        "Now, a man would have opened both gates, driven through and not bothered to close either gate." - Marc Clifton (The Lounge)

        L Offline
        L Offline
        Luc Pattyn
        wrote on last edited by
        #3

        Hi, your GUI contains one or more handlers to react on user input such as buttons being clicked. For each of these handlers you should make sure they finish in "no time", no matter what. "No time" means much less than one second if your prime concern is perfect GUI responsiveness, or whatever your users will find acceptable. Achieving that probably implies: - not using any Thread.Sleep() - not executing any loop waiting for something - not performing synchronous I/O (unless a small timeout is applied) - not waiting on something (such as a ManualResetEvent). Everything that will, is likely to, or might, take longer must be delegated to another thread/threadpool/backgroundworker, and you cannot wait for it, since that would be the same as doing it yourself in the handler. So it is not enough to use some backgroundworkers here and there, you must delegate everything that may take to long to threads/backgroundworkers. :)

        Luc Pattyn [Forum Guidelines] [My Articles]


        Avoiding unwanted divs (as in "articles needing approval") with the help of this FireFox add-in


        1 Reply Last reply
        0
        • M Marcus J Smith

          I have an application that has a simple user interface but quite a bit of code under the hood. The interface is a file processing form where the user chooses a file and then clicks a button to process the selection. The code disables all buttons on the form and has at it. Quite a bit of the code is reading from the file and I report how many records every 100 count and then call Application.DoEvents (I know this is bad that is why I am here). Part of this application uses BackGroundWorkers to run long SQL queries/updates where I use the .IsBusy property in a while loop and update a time elapsed message then call Application.DoEvents. I have a continuous progress bar that just runs all the time to show that something is happening but not necessarily reporting actual progress. I also have true multi-threading where I kick off threads and I have a few steps in the process where I wait for a few of those threads to complete before starting others, as part of that waiting process I call the Application.DoEvents call again. I have found many many articles online and forums where people say not to use Application.DoEvents, you should use backgroundworkers with ProgressChanged events. Well even though I implemented the Delegate step that they mention to set the value on the status bar for time elapsed, as soon as I take out the Application.DoEvents the form will report that it is not responding and if the user clicks on it they get the typical whited out form. What should I use instead to guarantee that I dont have code stepping on itself?


          CleaKO

          "Now, a man would have opened both gates, driven through and not bothered to close either gate." - Marc Clifton (The Lounge)

          L Offline
          L Offline
          Luc Pattyn
          wrote on last edited by
          #4

          Hi again, I'm adding a standard text of mine about cross-thread access to GUI Controls, since you will probably need such info anyway: Controls are not thread-safe, hence they should be touched (that is: their methods or properties called) only by the thread that created them, which normally is the main thread (aka GUI thread). Creating some controls on a different thread is unlikely to be successful, since all Controls get linked somehow: they reside on Forms, Forms are related to each other (by Parent, by Z-Order, etc), so normally all are created on a single thread. If you violate the “don’t touch Controls from another thread” rule and are running .NET version 2.0 or above you will get an InvalidOperationException (“Cross-thread operation not valid”), which should be remedied by changing the code. Do not set Control.CheckForIllegalCrossThreadCalls false, since that does hide the exception but does not cure the fundamental flaw in your code, so it just postpones the moment of failure, which typically will show as a non-responsive and possibly badly painted GUI. Here are some ways to get another thread: - explicitly launching a Thread instance - explicitly delegating some work to a ThreadPool thread - using a BackgroundWorker; a BGW is a separate thread with the advantage that two of its events (ProgressChanged and RunWorkerCompleted) execute on the GUI thread; however the bulk of the work normally is handled in the DoWork handler which runs on a distinct thread. - using timers other than System.Windows.Forms.Timer; the Forms timer ticks on the GUI thread, all other use different threads to handle the periodic event; - using asynchronous input/output, such as the DataReceived event of the SerialPort class Any of these touching a single method or property of a Control is sufficient to create havoc; there are 5 exceptions: - the InvokeRequired property - the Invoke, BeginInvoke, EndInvoke and CreateGraphics methods (the latter only if the handle for the control has already been created). If there is a need to touch the Control from another thread, one must use an Invoke pattern, which basically looks like this (using C# code, same can be done in VB.NET):

          public void SetText(string text) {
          if (myControl.InvokeRequired) {
          // this runs on the foreign thread and causes the
          // invocation of this same method on the GUI thread
          myControl.Invoke(new Action< string >(SetText),
          new object[] {text});
          } else {
          // this runs on t

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups