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
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C#
  4. What is the best method to figure out elapsed time in a BackgroundWorker thread?

What is the best method to figure out elapsed time in a BackgroundWorker thread?

Scheduled Pinned Locked Moved C#
questionperformance
10 Posts 4 Posters 2 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.
  • B Offline
    B Offline
    bbranded
    wrote on last edited by
    #1

    Hello, I am attempting to create a benchmarking software that reads the contents of files. I would like to report, every five seconds, the average speed per MB read, the speed in MB/sec. I don't think that calculating a TimeSpan will be the best method, as it will definitely be inaccurate overtime (increasing in inaccuracy). If I use a timer in the BackgroundWorker thread, how do I pass a variable to the ElapsedEventHandler that contains the amount of data read?

        private void timer\_Elapsed(object sender, ElapsedEventArgs e)
        {
            MessageBox.Show(AmountOfBytesRead);
        }
    
        public void ReadFiles(string TargetDirectory, bool RecursivePlz, string LogFilename)
        {
    
            DateTime StartOfReading = DateTime.Now;
    
            System.Timers.Timer timer = new System.Timers.Timer();
            timer = new System.Timers.Timer();
            timer.Elapsed += new ElapsedEventHandler(timer\_Elapsed);
            timer.Interval = 5000;
            timer.Start();
    
            ...
            //read some file(s) and record the amount of bytes read to a variable AmountOfBytesRead
    

    }

    Thanks, Matt

    I P 2 Replies Last reply
    0
    • B bbranded

      Hello, I am attempting to create a benchmarking software that reads the contents of files. I would like to report, every five seconds, the average speed per MB read, the speed in MB/sec. I don't think that calculating a TimeSpan will be the best method, as it will definitely be inaccurate overtime (increasing in inaccuracy). If I use a timer in the BackgroundWorker thread, how do I pass a variable to the ElapsedEventHandler that contains the amount of data read?

          private void timer\_Elapsed(object sender, ElapsedEventArgs e)
          {
              MessageBox.Show(AmountOfBytesRead);
          }
      
          public void ReadFiles(string TargetDirectory, bool RecursivePlz, string LogFilename)
          {
      
              DateTime StartOfReading = DateTime.Now;
      
              System.Timers.Timer timer = new System.Timers.Timer();
              timer = new System.Timers.Timer();
              timer.Elapsed += new ElapsedEventHandler(timer\_Elapsed);
              timer.Interval = 5000;
              timer.Start();
      
              ...
              //read some file(s) and record the amount of bytes read to a variable AmountOfBytesRead
      

      }

      Thanks, Matt

      I Offline
      I Offline
      Ian Shlasko
      wrote on last edited by
      #2

      A BackgroundWorker can report progress... Turn on the WorkerSupportsProgress flag, cast the "sender" to a BackgroundWorker and use that to send a progress report. You're supposed to send the completion percentage as an integer, but you can also supply a "state" object along with that, which could contain the bytes read. Now, if you want to get the amount of data read in the past X seconds, you need a rolling buffer... Maybe it could go something like this: 1) Every N bytes (Maybe every 500KB or so), the worker reports the bytes read as a progress event 2) The handler dumps that into a rolling buffer with a time stamp (DateTime), and maintains a pointer to the oldest record within the desired time span. 3) The speed is calculated as (BytesRead[current] - BytesRead[oldest]) / (TimeStamp[current] - TimeStamp[oldest]) and put into a class-level variable. 4) Every so often, your timer can just read that variable to report the speed (Or whatever you want to do with it)

      Proud to have finally moved to the A-Ark. Which one are you in?
      Author of the Guardians Saga (Sci-Fi/Fantasy novels)

      B L 2 Replies Last reply
      0
      • I Ian Shlasko

        A BackgroundWorker can report progress... Turn on the WorkerSupportsProgress flag, cast the "sender" to a BackgroundWorker and use that to send a progress report. You're supposed to send the completion percentage as an integer, but you can also supply a "state" object along with that, which could contain the bytes read. Now, if you want to get the amount of data read in the past X seconds, you need a rolling buffer... Maybe it could go something like this: 1) Every N bytes (Maybe every 500KB or so), the worker reports the bytes read as a progress event 2) The handler dumps that into a rolling buffer with a time stamp (DateTime), and maintains a pointer to the oldest record within the desired time span. 3) The speed is calculated as (BytesRead[current] - BytesRead[oldest]) / (TimeStamp[current] - TimeStamp[oldest]) and put into a class-level variable. 4) Every so often, your timer can just read that variable to report the speed (Or whatever you want to do with it)

        Proud to have finally moved to the A-Ark. Which one are you in?
        Author of the Guardians Saga (Sci-Fi/Fantasy novels)

        B Offline
        B Offline
        bbranded
        wrote on last edited by
        #3

        That's a great idea. I was thinking backward. The concern is cross-thread communication, and I think you addressed this. BackgroundWorker_ProgressChange() has access to the main thread, which includes all objects in the inclusive/root class, such as a class-wide variable to hold a value, and the Timer object and events. I still have the problem of accuracy, "left over" bytes when polling occurs. I'll get testing! Thanks very much, Matt

        modified on Wednesday, August 10, 2011 11:33 AM

        I 1 Reply Last reply
        0
        • B bbranded

          That's a great idea. I was thinking backward. The concern is cross-thread communication, and I think you addressed this. BackgroundWorker_ProgressChange() has access to the main thread, which includes all objects in the inclusive/root class, such as a class-wide variable to hold a value, and the Timer object and events. I still have the problem of accuracy, "left over" bytes when polling occurs. I'll get testing! Thanks very much, Matt

          modified on Wednesday, August 10, 2011 11:33 AM

          I Offline
          I Offline
          Ian Shlasko
          wrote on last edited by
          #4

          bbranded wrote:

          I still have the problem of accuracy, "left over" bytes when polling occurs.

          Not really, with the rolling buffer... You would keep the actual time of each report (You could even pass a DateTime+Integer struct from the worker to eliminate cross-thread delays), so you wouldn't have to make any assumptions... Your buffer would look something like:

          11:37:50 1500KB
          11:37:52 2000KB
          ...
          11:42:30 58000KB
          11:42:33 58500KB

          So you would get: (58500KB - 1500KB) / (11:42:33 - 11:37:50) = 57000KB / 4:43 And I'm too lazy to calculate that out, but that'll give you a KB/minute for the past ~5 minutes. And of course you can adjust the numbers to get whatever level of precision you want. The timer wouldn't actually be used to do any measurements, but rather to just report the results.

          Proud to have finally moved to the A-Ark. Which one are you in?
          Author of the Guardians Saga (Sci-Fi/Fantasy novels)

          B 1 Reply Last reply
          0
          • I Ian Shlasko

            A BackgroundWorker can report progress... Turn on the WorkerSupportsProgress flag, cast the "sender" to a BackgroundWorker and use that to send a progress report. You're supposed to send the completion percentage as an integer, but you can also supply a "state" object along with that, which could contain the bytes read. Now, if you want to get the amount of data read in the past X seconds, you need a rolling buffer... Maybe it could go something like this: 1) Every N bytes (Maybe every 500KB or so), the worker reports the bytes read as a progress event 2) The handler dumps that into a rolling buffer with a time stamp (DateTime), and maintains a pointer to the oldest record within the desired time span. 3) The speed is calculated as (BytesRead[current] - BytesRead[oldest]) / (TimeStamp[current] - TimeStamp[oldest]) and put into a class-level variable. 4) Every so often, your timer can just read that variable to report the speed (Or whatever you want to do with it)

            Proud to have finally moved to the A-Ark. Which one are you in?
            Author of the Guardians Saga (Sci-Fi/Fantasy novels)

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

            :thumbsup: my 5!

            1 Reply Last reply
            0
            • B bbranded

              Hello, I am attempting to create a benchmarking software that reads the contents of files. I would like to report, every five seconds, the average speed per MB read, the speed in MB/sec. I don't think that calculating a TimeSpan will be the best method, as it will definitely be inaccurate overtime (increasing in inaccuracy). If I use a timer in the BackgroundWorker thread, how do I pass a variable to the ElapsedEventHandler that contains the amount of data read?

                  private void timer\_Elapsed(object sender, ElapsedEventArgs e)
                  {
                      MessageBox.Show(AmountOfBytesRead);
                  }
              
                  public void ReadFiles(string TargetDirectory, bool RecursivePlz, string LogFilename)
                  {
              
                      DateTime StartOfReading = DateTime.Now;
              
                      System.Timers.Timer timer = new System.Timers.Timer();
                      timer = new System.Timers.Timer();
                      timer.Elapsed += new ElapsedEventHandler(timer\_Elapsed);
                      timer.Interval = 5000;
                      timer.Start();
              
                      ...
                      //read some file(s) and record the amount of bytes read to a variable AmountOfBytesRead
              

              }

              Thanks, Matt

              P Offline
              P Offline
              PIEBALDconsult
              wrote on last edited by
              #6

              bbranded wrote:

              I don't think that calculating a TimeSpan will be the best method, as it will definitely be inaccurate overtime (increasing in inaccuracy).

              Only if you do it wrong.

              B 1 Reply Last reply
              0
              • P PIEBALDconsult

                bbranded wrote:

                I don't think that calculating a TimeSpan will be the best method, as it will definitely be inaccurate overtime (increasing in inaccuracy).

                Only if you do it wrong.

                B Offline
                B Offline
                bbranded
                wrote on last edited by
                #7

                Oh please please, share your wisdom. It's torture that you're keeping it all to yourself.

                P 1 Reply Last reply
                0
                • B bbranded

                  Oh please please, share your wisdom. It's torture that you're keeping it all to yourself.

                  P Offline
                  P Offline
                  PIEBALDconsult
                  wrote on last edited by
                  #8

                  What? Oh. Well I suspect you're considering calculating TimeSpans and adding them together rather than keeping the beginning time and calculating the whole elapsed time. I'd likely use a StopWatch anyway, but that's just me.

                  B 1 Reply Last reply
                  0
                  • P PIEBALDconsult

                    What? Oh. Well I suspect you're considering calculating TimeSpans and adding them together rather than keeping the beginning time and calculating the whole elapsed time. I'd likely use a StopWatch anyway, but that's just me.

                    B Offline
                    B Offline
                    bbranded
                    wrote on last edited by
                    #9

                    Thanks. I'll look into that direction to solve the problem as well.

                    1 Reply Last reply
                    0
                    • I Ian Shlasko

                      bbranded wrote:

                      I still have the problem of accuracy, "left over" bytes when polling occurs.

                      Not really, with the rolling buffer... You would keep the actual time of each report (You could even pass a DateTime+Integer struct from the worker to eliminate cross-thread delays), so you wouldn't have to make any assumptions... Your buffer would look something like:

                      11:37:50 1500KB
                      11:37:52 2000KB
                      ...
                      11:42:30 58000KB
                      11:42:33 58500KB

                      So you would get: (58500KB - 1500KB) / (11:42:33 - 11:37:50) = 57000KB / 4:43 And I'm too lazy to calculate that out, but that'll give you a KB/minute for the past ~5 minutes. And of course you can adjust the numbers to get whatever level of precision you want. The timer wouldn't actually be used to do any measurements, but rather to just report the results.

                      Proud to have finally moved to the A-Ark. Which one are you in?
                      Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                      B Offline
                      B Offline
                      bbranded
                      wrote on last edited by
                      #10

                      Thanks very much! This is very far from perfect, but will give others a good starting point to address this issue. I'll open source the final project over at mbrownnyc.wordpress.com shortly.

                          private void \_bw\_DoWork(object sender, DoWorkEventArgs e)
                          {
                              //break up and assign the arguments passed by the methods:
                              string\[\] CommandArguments = e.Argument.ToString().Split('#');
                      
                              string TargetDirectory = CommandArguments\[0\];
                              bool RecursivePlz = Boolean.Parse(CommandArguments\[1\]);
                              string LogFilename = CommandArguments\[2\];
                      
                              ReadFiles(TargetDirectory, RecursivePlz, LogFilename);
                      
                          }
                      
                          public void ReadFiles(string TargetDirectory, bool RecursivePlz, string LogFilename)
                          {
                      
                              
                              //take readsize and divide it by 1048576 (1MB)...
                              // calculate how many operations it takes to complete the read of 1MB
                              int readsize = 65536;
                              double ReadOpsPerMB = readsize / 1048576;
                              //see "use the ReadOpsPerMB" below
                      
                              TargetDirectory = TargetDirectory.ToLower();
                      
                              //exclude dfsrprivate folders
                              if (!TargetDirectory.Contains("dfsrprivate"))
                              {
                      
                                  //find the directory
                                  if (Directory.Exists(TargetDirectory))
                                  {
                                      //find the files in this directory
                                      string\[\] FileList = Directory.GetFiles(TargetDirectory);
                      
                                      int BytesReadInRound = 0;
                      
                                      //check files in this directory
                                      foreach (string ffile in FileList)
                                      {
                      
                                          FileInfo finfo = new FileInfo(ffile);
                                          if (finfo.Exists)
                                          {
                                              //get the full file size
                                              int SizeOfFile = Int32.Parse(finfo.Length.ToString());
                      
                                              //adjust filestream buffer to be larger than the readsize, this will not force a read, and allow us to count the enumerations
                                              FileStream readStream = new FileStream(ffile, FileMode.Open, FileAccess.Read, FileShare.None, readsize + 1);
                                              BinaryReader binReader = new BinaryReader(readStream);
                      
                                              string Status = "";
                      
                                              bool Readthefile = true;
                      
                                              try
                                              {
                      
                      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