4

Ok so I have a fairly simple question which I could not find a concise answer for. I am wondering if i need to worry about calling a lock() statement when reading the elapsed property of a Stopwatch while it is still running.

Also is a Stopwatch what I should be using to measure run-times of a thread. I have read in other similar questions a DispatchTimer could be used. I have also looked into using events, however that seemed like a lot of overhead for something so simple, please inform me if that is just plain wrong and I should be using events. Some simple code to illustrate what I am talking about.

 class foo
 {
      private bool _isRunning { get; set; }
      private Stopwatch sw { get; set; }
      public void StartThread()
      {
          this._isRunning = true;
          new Thread(new ThreadStart(this.DoWork)).Start();
          this.sw.Restart();
      }     
      public void StopThread()
      {
          this._isRunning = false;
          this.sw.Stop();
      }
      private void DoWork()
      {
          while(this._isRunning)
          {
               //Do Stuff
          }
      }
      public TimeSpan GetRuntime()
      {
          return this.sw.Elapsed;
      }
      public foo()
      {
          _isRunning = false;
          sw = new Stopwatch();
      }
 }

Say in an application using the above class I were to call GetRuntime() from a different thread before I stop the Stopwatch would I need to add a lock() statement to ensure that I get the correct data, and that I wont be blocking the Stopwatch from continuing to run. Or am i correct in thinking that it does not need a lock() and will be fine as is.

I do understand that you can theoretically run as many reads as you would like, I am just curious seeing as the Elapsed properties backing store is constantly being written to if that changed things or not. I have read a lot of information about thread safety, but I am just looking for a clarification and confirmation I am indeed thinking about this correctly.

Nomad101
  • 1,688
  • 11
  • 16
  • Does this answer your question? [Is Stopwatch.ElapsedTicks threadsafe?](https://stackoverflow.com/questions/6664538/is-stopwatch-elapsedticks-threadsafe) – Jason C May 26 '21 at 22:23

1 Answers1

5

The MSDN documentation states, in regard to Stopwatch, "Any instance members are not guaranteed to be thread safe." Note that there is definitely a theoretical vulnerability here, as it uses a 'long' tick count internally and updating a long on 32-bit processors is not an atomic operation. You can potentially see partially updated (and hence corrupted) values. You probably won't notice until the Ticks happens to run past the 32-bit boundary, at which point you might run into a very unexpected rare error (you could potentially read Int32.MaxValue, followed by 0, followed by Int32.MaxValue + 1, yielding a very large difference in elapsed times if you query it at just the wrong moment.)

Dan Bryant
  • 27,329
  • 4
  • 56
  • 102
  • Ok so I was right to question this. Thanks for the information, however just a bit of clarification, if I were to stick with using just the 32bit return values I would be ok, or are you saying that even the 32bit returns are based off of the 64bit backing store? I know the 64bit values can lead to reading only half of the correct values which is why this question came up. – Nomad101 May 09 '13 at 17:55
  • 1
    @Nomad101, I suspect that, internally, everything is computed based on the tick counts. I definitely wouldn't rely on other operations being thread-safe, as it's an implementation detail and not guaranteed by the documentation. – Dan Bryant May 09 '13 at 17:56
  • Alright that makes a lot of sense thanks for the information and very quick response. – Nomad101 May 09 '13 at 17:57
  • 4
    @Nomad101: The documentation says **not guaranteed to be thread safe**. Asking "well, if I only stick to this part of the feature set, is it safe?" is then basing safety-and-correctness-impacting decisions on implementation details that are subject to change. Your attitude towards thread safety should not be "what's the most dangerous operation I can get away with?" but rather "how can I *guaranteee* that I safely access this data structure?" – Eric Lippert May 09 '13 at 19:19
  • @EricLippert I was asking, more clarifying, about the issue of the differences in 32bit values and 64bit values in terms of thread safety. I have no idea what you are getting at with your comment, considering I never mentioned what the most dangerous implementation would be, in reality if you actually read what I said in my question I was making sure that I did indeed need to use a lock() statement, then in the comment was making sure I fully understood what he meant. So yea your comment is completely off base. – Nomad101 May 09 '13 at 19:22
  • 2
    @Nomad101: You asked "If I was to stick with using the 32 bit return values would I be OK?" The documentation does not say "If you stick with the 32 bit return values then the operation is threadsafe." It says the opposite: **not guaranteed to be threadsafe**. Asking "well, if I stick to this particular usage pattern, is it threadsafe?" indicates that you're considering trying to do something dangerous. – Eric Lippert May 09 '13 at 19:27
  • 1
    @EricLippert I can copy and paste out of context too look at this. At the beginning of the comment, "Thanks for the information, however just a bit of clarification" and at the end of the comment, "I know the 64bit values can lead to reading only half of the correct values which is why this question came up.", So where exactly did I say I was going to do something dangerous, or is asking for clarification now saying that you are going to do something? – Nomad101 May 09 '13 at 19:30