【问题标题】:Perform async operations with Hangfire instead of Tasks使用 Hangfire 而不是 Tasks 执行异步操作
【发布时间】:2023-03-25 13:14:01
【问题描述】:

我有 4 个执行不同操作的类,这 2 个任务中的每一个都应该同步运行。

我当前的实现工作正常,但有时会出现奇怪的滞后,并且某些 processors 无法运行。这可能是我想的线程问题。

我想重构代码以使用Hangfire 库或任何其他方式来保持程序正常工作。我不知道如何财产做到这一点,并希望得到任何帮助。

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);
        }
 }

【问题讨论】:

    标签: c# multithreading task hangfire


    【解决方案1】:

    您以错误的方式使用任务。任务应该是非阻塞或短期项目。

    基本上这里发生的是你启动的任务永远不会结束并且永远不会释放他们的线程。这会导致线程池的部分线程阻塞。

    改变事物有多种方式:

    1) 非阻塞任务:

    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) 使用阻塞线程但不影响线程池:

    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);
        }
     }
    

    【讨论】:

      【解决方案2】:

      Hangfire 主要用于触发和忘记任务,您可以在其中排队、安排和重新排队作业,如果您想要实现这些,可以通过 nuget 安装,然后使用以下语法

      BackgroundJob.Enqueue(() => RunSyncProcess(processors1));
      

      因此,为了重构代码,您需要决定是要安排作业还是要在等待新任务之前等待先前任务的成功完成,这实际上取决于您想要什么去实现。

      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!
      
          BackgroundJob.Enqueue(() => RunSyncProcess(processors1));
          BackgroundJob.Enqueue(() => RunSyncProcess(processors2));
      }
      
       public void RunSyncProcess(CommonProcessor[] processors)
       {
          while (true)
          {
               foreach (var processor in processors)
               { 
                 // do some job 
               }
          }
       }
      

      您不必等待所有这些,因为这些将在幕后开始,您的 UI 将响应。请记住,当您要使用 hangfire 时,这些方法需要公开。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-24
        • 2011-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-27
        • 1970-01-01
        • 2015-11-09
        相关资源
        最近更新 更多