Many of us have been confronted many times with the need to calculate any value in a method. And the value that is calculated must be stored somewhere (for example, in a static class field). For multithreaded algorithms this is:

lock (syncObj) Interlocked.Increment(ref int) 

But for asynchronous methods, any blocking method is very undesirable. I tried to get by with the BlockingCollection -based queue - but unfortunately the methods work very quickly and the transfer / retrieval rate of the collection is not enough.

How exactly can you get out of the situation?

  • one
    Tell us a little more about the meaning of this counter. - VladD
  • @VladD, let's take the simplest - how many times the method worked. Or how many times the value of the variable in the method has changed. - Alexis
  • In this case, I would most likely return the number of changes to the variable in the method as part of the return value. - VladD
  • @VladD, in principle, understandable. Either return the value from the method (which is also not entirely convenient / correct), or use all the same methods for a multithreaded implementation. - Alexis
  • one
    Depending on the meaning of the counter. If this is a progress indicator, then through IProgress . If this is the result, then through the return value. Side effects should be avoided, especially in multi-threaded programming. - VladD pm

1 answer 1

Summarize the discussion in the comments in response.

If we are talking about asynchronous code, it makes sense not to produce side effects. For example, because they require synchronization.

Therefore, I would recommend to try other approaches, depending on the meaning of the counter.

  • If the counter is needed to accumulate any information resulting from the method run, it is worth returning the increment of the counter as part of the return value. In the end, it is part of the function result.
  • If the counter is needed to report on the run of a function, it is worth passing to the IProgress<T> function, and let the function report the progress through it. The standard implementation of Progress<T> marshalls values ​​into a UI stream, and thus should not slow down the progress of calculations.
  • One clarification - is the standard implementation of Progress <T> thread safe? Suppose several threads send reports to Progress <int> (ReportProgress), in the ReportProgress method there is a simple increment of values. Will there be a loss of accuracy? And the second question - if there is synchronization - what is the internal structure of Progress <T>? what is used there (queue, delegate, etc.)? - Alexis
  • one
    @Alexis: as far as I understand, Progress<T> simply calls the delegate passed to it in the constructor, and if Progress<T> created in the UI flow, the delegate is called in the same UI flow, regardless of where the Report call occurred. - VladD 9:01 pm
  • one
    So there will be no losses, it's just a call on the dispatcher. - VladD