Search code examples
c#multithreadingtaskhangfire

Perform async operations with Hangfire instead of Tasks


I have 4 classes that perform different actions, each of the 2 tasks should run syncronously.

My current implementation works fine, but sometimes there are strange lags and some of the processors do not run. This could be the threads issue I suppose.

I would like to refactor the code to use Hangfire library or any other way to keep the program working correctly. I'm not sure how to property do that and would appreciate any help.

public void Run()
{
        var processors1 = new CommonProcessor[] { new AProcessor(), new BProcessor() };  
        //AProcessor should be first!
        var processors2 = new CommonProcessor[] { new CProcessor(), new DProcessor() }; 
        //CProcessor should be first!

        Task task1 = Task.Run(() => RunSyncProcess(processors1);
        Task task2 = Task.Run(() => RunSyncProcess(processors2);

        Task.WaitAll(task1, task2);
}

 private void RunSyncProcess(CommonProcessor[] processors)
 {
        while (true)
        {
             foreach (var processor in processors)
             { 
               // do some job 
             }
             Thread.Sleep(frequency);
        }
 }

Solution

  • You are using Tasks the wrong way. Tasks are supposed to be non blocking or short term lived items.

    Basically what happens here is that you launch Tasks which never end and never release their thread. This will result in blocking some threads of the ThreadPool.

    There are multiple way to change things:

    1) Non blocking tasks:

    public void Run()
    {
            var processors1 = new CommonProcessor[] { new AProcessor(), new BProcessor() };  
            //AProcessor should be first!
            var processors2 = new CommonProcessor[] { new CProcessor(), new DProcessor() }; 
            //CProcessor should be first!
    
            Task task1 = RunSyncProcess(processors1);
            Task task2 = RunSyncProcess(processors2);
    
            Task.WhenAll(task1, task2);
    }
    
     private async Task RunSyncProcess(CommonProcessor[] processors)
     {
        while (true)
        {
             foreach (var processor in processors)
             { 
               // do some job 
             }
             await Task.Delay(TimeSpan.FromMilliseconds(frequency));//will free threadpool while waiting
        }
     }
    

    2) Using blocking threads but without impacting threadpool:

    public void Run()
    {
        var processors1 = new CommonProcessor[] { new AProcessor(), new BProcessor() };  
        //AProcessor should be first!
        var processors2 = new CommonProcessor[] { new CProcessor(), new DProcessor() }; 
        //CProcessor should be first!
    
        Thread t1 = new Thread(() => RunSyncProcess(processors1));
        t1.Start();
        Thread t2 = new Thread(() => RunSyncProcess(processors1));
        t2.Start();
    
        t1.Join();
        t2.Join();
    }
    
     private void RunSyncProcess(CommonProcessor[] processors)
     {
        while (true)
        {
             foreach (var processor in processors)
             { 
               // do some job 
             }
             Thread.Sleep(frequency);
        }
     }