-1

I have a .NET Standard library that is able to report back its progress. I would like the program not to block until the progress reporting method has completed. Instead I would like a Fire-And-Forget pattern where the work can continue inside DoWork()

class Foo
{
   public delegate void ProgressEvent(double progress, double max);
   public ProgressEvent ReportProgress { get; set; }

   public void DoSomeWork()
   {
      for(int i = 0; i < 1000; i ++)
      {
         // Do work
         ReportProgress?.Invoke(i, 1000);   // I do not want to wait for the method to return here
      }
   }
}

So far, I have put it as a requirement that the method body assigned to ReportProgress must execute quickly. But if there is a good coding solution, I would not like to rely on requirements.

There is the possibility to wrap the invocation of ReportProgress in a new thread, but that seems inefficient - that will spawn 1000 threads.

This question suggests that I should somehow expose a ThreadPool in my class, but I am not sure that this makes sense: Simplest way to do a fire and forget method in C#?

How would you approach this situation?

EDIT: I belive that the user of the class is using it like this. Note that there is a potential slow update of a remote database. This customer was the reason I needed to rethink the struture.

void HandleRequest(int requestID)
{
    
    Thread workerThread = new Thread(()=>
    {
        double currentProgress = 0;
        Foo f = new Foo();
        f.ReportProgress = (progress, max) =>
        {
            double newProgress = progress/max;
            if(newProgress > currentProgress)
            {
                currentProgress = newProgress;
                UpdateRemoteDataBase(currentProgress, requestID);
            }
        }
        t.DoWork();
    });
}

folmerbrem
  • 41
  • 7
  • 1
    Try the key word ```async``` ```await``` – MichaelMao Dec 02 '20 at 07:54
  • @folmerbrem Have you considered to use `IProgress` ([1](https://blog.stephencleary.com/2012/02/reporting-progress-from-async-tasks.html))? – Peter Csala Dec 02 '20 at 08:05
  • @MichaelMao Yes I was looking into the async pattern as it really seems like the way to go. But I have a hard time putting it into my context when using delegates. An example would really be helpful if you can spare a few moments. – folmerbrem Dec 02 '20 at 10:15
  • Could you provide an example how will you use this class – MichaelMao Dec 02 '20 at 10:50
  • @MichaelMao I added a code that likely represents how the customer is using the library – folmerbrem Dec 02 '20 at 11:09
  • If your user use a new thread to run this then I think it will not get block? – MichaelMao Dec 02 '20 at 11:30
  • Yes but I cannot control what my user is doing. I can only point to recommendations, but I would like to code my way out of this instead by firing the Invoke and getting on with DoWork. – folmerbrem Dec 02 '20 at 12:53
  • What is you ```t.DoWork()``` mean? ```Foo.DoSomeWork() ```? – MichaelMao Dec 04 '20 at 03:49

1 Answers1

0

How about just wrap your DoSomework with Thread

 class Foo
    {
        public delegate void ProgressEvent(double progress, double max);
        public ProgressEvent ReportProgress { get; set; }

        public void DoSomeWork()
        {
            Thread workerThread = new Thread(() =>
            {
                for (int i = 0; i < 1000; i++)
                {
                    // Do work
                    Thread.Sleep(1000);
                    ReportProgress?.Invoke(i, 1000);   // I do not want to wait for the method to return here
                }
            });
            workerThread.Start();
            return;
        }
    }
MichaelMao
  • 2,596
  • 2
  • 23
  • 54