如何为特定的后台任务确定静态类对象的作用域?

更新时间:2023-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。