如何為特定的后臺任務確定靜態類對象的作用域?

更新時間:2024-02-28 23:27:03

問題闡述

正在考慮

public class BackgroundJob{
   public string jobName{get;set;}
   ...
}

AppConfig.cs

public class AppConfig{
   public static BackgroundJob currentJob{get;set;}
}

BackEarth jobService.cs

public interface IBackgroundJobService
{ ... }

public class BackgroundJobService : IBackgroundJobService
{
    private readonly ServiceScopFactory _serviceScopFactory;
    public BackgroundJobService(ServiceScopFactory serviceScopFactory)
    {
        _serviceScopFactory = serviceScopFactory;
    }
    public async Task RunBackgroundJobTest1()
    {
        using (var serviceScope = _serviceScopeFactory.CreateScope())
        {
            AppConfig.currentJob = new(){ jobName = "job1" };

                var idx = 0;
                for (int i = 0; i <= 1000; i += 100)
                {
                    idx++;
                    await Task.Delay(1000);
                    Console.WriteLine($"===> jobName = {currentJob.jobname}");
                }
        }
    }

    public async Task RunBackgroundJobTest2()
    {
        using (var serviceScope = _serviceScopeFactory.CreateScope())
        {
            AppConfig.currentJob = new(){ jobName = "job2" };

                var idx = 0;
                for (int i = 0; i <= 1000; i += 100)
                {
                    idx++;
                    await Task.Delay(1000);
                    Console.WriteLine($"===> jobName = {currentJob.jobname}");
                }
        }
    }
}

執行:

public class TestController : Controller
{
   private readonly IBackgroundJobClient _backgroundJobClient; //hangfire
   public TestController(IBackgroundJobClient backgroundJobClient)
   {
      _backgroundJobClient = backgroundJobClient;
   }
   [HttpGet("test")]
   public IActionResult Test()
   {
       _backgroundJobClient.Enqueue<IBackgroundJobService>(x=>x.RunBackgroundJobTest1()); //log ===> jobName = job2
       _backgroundJobClient.Enqueue<IBackgroundJobService>(x=>x.RunBackgroundJobTest2()); //log ===> jobName = job2
   }
}
因此,AppConfig.currentJob不保留來自/內部的第一個值ServiceScop1,但它已被內部的最后一個任務重新初始化ServiceScope2
問題:有沒有人建議我為此目的正確實施?
不勝感激。謝謝

精準答案

我不清楚您試圖實現的目標。無論如何,正如我理解💮您的問題,您可以嘗試下面的代碼。它將使當前作業成為您處理的本地作業。與[ThreadStatic]不同,如果進程更改線程,這不會失敗:

public class AppConfig{
   private static System.Threading.AsyncLocal<BackgroundJob> _currentJob {get;} 
        = new System.Threading.AsyncLocal<BackgroundJob>();

 public static BackgroundJob currentJob {
     get {return _currentJob.Value;}
     set {_currentJob.Value = value;}
  }   
}

請注意,此行為并未鏈接⛄到ScopeServiceFacters。若要擁有鏈接到作用域的完全依賴項注ꦇ入,您需要刪除Statics。