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. C#
  4. BackgroundWorker never completes it's work

BackgroundWorker never completes it's work

Scheduled Pinned Locked Moved C#
announcementhtmlcomquestion
5 Posts 2 Posters 0 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.
  • C Offline
    C Offline
    Clive D Pottinger
    wrote on last edited by
    #1

    I am working on creating a rich text box control to serve as a "visible" log of events. In order for it to work properly, it must be able to accept log entries from different threads. I tried following the recommendations given by Microsoft on this page: http://msdn2.microsoft.com/en-ca/library/ms171728.aspx The recommended method in the examples is to call a BackgroundWorker and perform the update in the BackgroudWorker's RunWorkerCompleted event. In order to ensure that the text was available to the RunWorkerCompleted event, I added a DoWork event that, essentially, takes the text from it's EventArgs.Argument and puts it in the .Result area. I have included a stripped down version of the code below. Executing this with only one call to AddEntry works wonderfully: AddEntry calls AddEntryInBackground.RunWorkerAsync, DoWork is executed, then RunWorkerCompleted and the desired text shows up in the textbox. However, when there is a second call to AddEntry, it all falls apart. It seems as though the first call's DoWork execution is interrupted by the second call and never completes. The second call waits forever for IsBusy to be false. I am unable to find anything that may explain why this occurring - Microsoft recommends this procedure as the "thread-safe" way to avoid simultaneous access to a form's control - which it does (in the same way that deliberately driving your car off a cliff keeps you from accidentally driving your car off a cliff). It appears that the BackgroundWorker only "works" for a very limited amount of time, after which control is passed back to the main thread and the BackgroundWorker remains in a permanent unfinished state. Can anyone point me in the right direction? Many thanks, The main formusing System; using System.ComponentModel; using System.Threading; using System.Windows.Forms; namespace TestVisibleLog { public class VisibleLog : RichTextBox { private string timeStampFmt; private int maximumBytes; private string[] timeStampTokens; private BackgroundWorker AddEntryInBackground; public VisibleLog ( ) { this.Enabled = false; // must be set to true by the controlling process. timeStampFmt = ""; maximumBytes = 512; timeStampTokens = "dow,yoc,moy,dom,hh,mm,ss".Split(','); this.Text = ""; // Create a background worker that will be responsible for updating the control's text with entries from

    S 1 Reply Last reply
    0
    • C Clive D Pottinger

      I am working on creating a rich text box control to serve as a "visible" log of events. In order for it to work properly, it must be able to accept log entries from different threads. I tried following the recommendations given by Microsoft on this page: http://msdn2.microsoft.com/en-ca/library/ms171728.aspx The recommended method in the examples is to call a BackgroundWorker and perform the update in the BackgroudWorker's RunWorkerCompleted event. In order to ensure that the text was available to the RunWorkerCompleted event, I added a DoWork event that, essentially, takes the text from it's EventArgs.Argument and puts it in the .Result area. I have included a stripped down version of the code below. Executing this with only one call to AddEntry works wonderfully: AddEntry calls AddEntryInBackground.RunWorkerAsync, DoWork is executed, then RunWorkerCompleted and the desired text shows up in the textbox. However, when there is a second call to AddEntry, it all falls apart. It seems as though the first call's DoWork execution is interrupted by the second call and never completes. The second call waits forever for IsBusy to be false. I am unable to find anything that may explain why this occurring - Microsoft recommends this procedure as the "thread-safe" way to avoid simultaneous access to a form's control - which it does (in the same way that deliberately driving your car off a cliff keeps you from accidentally driving your car off a cliff). It appears that the BackgroundWorker only "works" for a very limited amount of time, after which control is passed back to the main thread and the BackgroundWorker remains in a permanent unfinished state. Can anyone point me in the right direction? Many thanks, The main formusing System; using System.ComponentModel; using System.Threading; using System.Windows.Forms; namespace TestVisibleLog { public class VisibleLog : RichTextBox { private string timeStampFmt; private int maximumBytes; private string[] timeStampTokens; private BackgroundWorker AddEntryInBackground; public VisibleLog ( ) { this.Enabled = false; // must be set to true by the controlling process. timeStampFmt = ""; maximumBytes = 512; timeStampTokens = "dow,yoc,moy,dom,hh,mm,ss".Split(','); this.Text = ""; // Create a background worker that will be responsible for updating the control's text with entries from

      S Offline
      S Offline
      S Senthil Kumar
      wrote on last edited by
      #2

      That is not the way BackgroundWorkers are meant to be used. They are typically created to do some background work, report progress (if any) on the UI thread, and then indicate completion of the background work on the UI thread. If all you need to do is update text from a non-UI thread, you are much better off using Control.Invoke[^] or Control.BeginInvoke[^]. Your code would then look like

      delegate void StringInvoker(string t);

      void AddEntry(string text)
      {
      if (this.InvokeRequired)
      {
      this.Invoke(new StringInvoker(AddEntry), text); // recursively calls AddEntry, but the call comes on the UI thread, so InvokeRequired will be false.
      return;
      }
      this.Text = ...; // RunWorker_Completed logic goes here.
      }
      }

      Regards Senthil [MVP - Visual C#] _____________________________ My Blog | My Articles | My Flickr | WinMacro

      C 2 Replies Last reply
      0
      • S S Senthil Kumar

        That is not the way BackgroundWorkers are meant to be used. They are typically created to do some background work, report progress (if any) on the UI thread, and then indicate completion of the background work on the UI thread. If all you need to do is update text from a non-UI thread, you are much better off using Control.Invoke[^] or Control.BeginInvoke[^]. Your code would then look like

        delegate void StringInvoker(string t);

        void AddEntry(string text)
        {
        if (this.InvokeRequired)
        {
        this.Invoke(new StringInvoker(AddEntry), text); // recursively calls AddEntry, but the call comes on the UI thread, so InvokeRequired will be false.
        return;
        }
        this.Text = ...; // RunWorker_Completed logic goes here.
        }
        }

        Regards Senthil [MVP - Visual C#] _____________________________ My Blog | My Articles | My Flickr | WinMacro

        C Offline
        C Offline
        Clive D Pottinger
        wrote on last edited by
        #3

        Thank you Senthil. When I read the page on the MSDN site, the Invoke seemed to make the most sense. However, I ran into a problem which I thought might have been caused by using Invoke. Since Microsoft says

        "The preferred way to implement multithreading in your application is to use the BackgroundWorker component"

        I thought I would set the code up that way. Now I believe my initial problem was not related to my use of Invoke. I will put the code back and track down my problem. Thanks again. I will figure out C#, and by the year 2034 I'll be qualified to write thread-safe, XAML-based, SQL powered Hello World programs on any XP systems that may still be around :sigh:

        Clive Pottinger Victoria, BC

        1 Reply Last reply
        0
        • S S Senthil Kumar

          That is not the way BackgroundWorkers are meant to be used. They are typically created to do some background work, report progress (if any) on the UI thread, and then indicate completion of the background work on the UI thread. If all you need to do is update text from a non-UI thread, you are much better off using Control.Invoke[^] or Control.BeginInvoke[^]. Your code would then look like

          delegate void StringInvoker(string t);

          void AddEntry(string text)
          {
          if (this.InvokeRequired)
          {
          this.Invoke(new StringInvoker(AddEntry), text); // recursively calls AddEntry, but the call comes on the UI thread, so InvokeRequired will be false.
          return;
          }
          this.Text = ...; // RunWorker_Completed logic goes here.
          }
          }

          Regards Senthil [MVP - Visual C#] _____________________________ My Blog | My Articles | My Flickr | WinMacro

          C Offline
          C Offline
          Clive D Pottinger
          wrote on last edited by
          #4

          Thanks again, Senthil. I was wondering... do you have any idea why my use of BackgroundWorker failed? I thought I set it up correctly. Now that I have been exposed to it, I think I see were it could be useful in the future and I'd like to know that I can use it without getting locked up.

          Clive Pottinger Victoria, BC

          S 1 Reply Last reply
          0
          • C Clive D Pottinger

            Thanks again, Senthil. I was wondering... do you have any idea why my use of BackgroundWorker failed? I thought I set it up correctly. Now that I have been exposed to it, I think I see were it could be useful in the future and I'd like to know that I can use it without getting locked up.

            Clive Pottinger Victoria, BC

            S Offline
            S Offline
            S Senthil Kumar
            wrote on last edited by
            #5

            BackgroundWorker is meant to be used for running long running operations in the background - essentially operations for which you would create a Thread yourself. The difference is that you can use the BackgroundWorker to report progress and completion without having to manually use Invoke or BeginInvoke. Bulk file copy and application initialization (with a splash screen indicating progress) are two places where a BackgroundWorker would work well. The reason I suggested that you use Invoke/BeginInvoke was that you were not running any big operations in DoWork, you were simply using it to marshal the call to the UI thread by setting the Result property. That is exactly what Invoke/BeginInvoke is supposed to do. What's more, the BackgroundWorker's DoWork will run on a threadpool thread - this is in addition to the other thread on which you're doing the actual work. Invoke/BeginInvoke will not use a threadpool thread, it simply causes the delegate to execute on the UI thread.

            Regards Senthil [MVP - Visual C#] _____________________________ My Blog | My Articles | My Flickr | WinMacro

            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