Asp.Net Core - 在任务中使用会话变量

时间:2017-08-09 15:54:00

标签: c# asp.net asp.net-core

我正在使用Asp.Net应用程序构建模拟器,其中模拟作为单独的任务完成。我在访问此任务中处理的数据时遇到问题。

我试图访问我创建的任务或威胁,但是没有找到跟踪已创建任务的方法。

我也试过使用Session,但是在请求完成后我再也无法访问Session了,所以后台任务会因错误而停止。

LatheController:

public class LatheController : Controller
{
    private readonly ApiDbContext _dbContext;
    private static ILatheService _latheService;

    public LatheController(ApiDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    [HttpGet]
    public LatheCell GetLatheCell()
    {
        if (_latheService == null)
        {
           _latheService = new LatheService();

            _latheService.Start(lc);
        }

        return _latheService.GetLatheCell();
    }


    [HttpGet("{id}")]
    public LatheCell GetLatheCell([FromRoute]int id)
    {
        return AppHttpContext.Current.Session.GetObjectFromJson<LatheCell>("latheCell");
    }
}

LatheService:

public class LatheService : ILatheService
{
    private LatheSimulator _latheSim;

    public void Start(LatheCell lc)
    {
        _latheSim = new LatheSimulator(lc);

        Task task = new Task( () => { _latheSim.Start(); });
        task.Start();
    }

    public LatheCell GetLatheCell()
    {
        return _latheSim.GetLatheCell();
    }
}

LatheSimulator:

    public class LatheSimulator
{
    private LatheCell _latheCell;
    private bool _keepRunning;

    public LatheSimulator(LatheCell latheCell)
    {
        _latheCell = latheCell;
    }


    public void Start()
    {
        _keepRunning = true;
        Simulation();
    }

    public void Stop()
    {
        _keepRunning = false;
    }

    public LatheCell GetLatheCell()
    {
        return _latheCell;
    }


    private void Simulation()
    {
        while (_keepRunning)
        {
            _latheCell.RunningCycle++;
            //// The simuation ///

            AppHttpContext.Current.Session.SetObjectAsJson("latheCell", _latheCell);

            //Sleep operation to simulate speed of the conveyor
            System.Threading.Thread.Sleep(_latheCell.ConveyorIn.Speed);
        }
    }
}

启动

public void ConfigureServices(IServiceCollection services)
    {
        /// ... some other configurations

        services.AddMvc();
        services.AddDistributedMemoryCache();
        services.AddSession();
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    }
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    { 
       ///....
       app.UseSession();
       AppHttpContext.Services = app.ApplicationServices;
      /// .....
    }

AppHttpContext:

public static class AppHttpContext
{
    static IServiceProvider services = null;

    public static IServiceProvider Services
    {
        get { return services; }
        set
        {
            if (services != null)
            {
                throw new Exception("Can't set once a value has already been set.");
            }
            services = value;
        }
    }

    public static HttpContext Current
    {
        get
        {
            IHttpContextAccessor httpContextAccessor = services.GetService(typeof(IHttpContextAccessor)) as IHttpContextAccessor;
            return httpContextAccessor?.HttpContext;
        }
    }
}

我知道我可以使用数据库,但因为我将在模拟中每5秒调用一次数据库,所以我希望将模拟器保留在内存中以获得性能。

如果有人能让我朝着正确的方向前进,我将非常感激。我现在已经抓了好几天了。

1 个答案:

答案 0 :(得分:0)

  

我想将模拟器保留在内存中以获得性能。

问题是,如果App Pool重新开始并且App Domain重新启动,您将丢失正在运行任务的所有内容。

理想情况下,我们需要在SQL Server等持久存储中存储数据。我说每5秒调用一次数据库并不是什么大问题,除非你要查询大量数据要处理。

我们通常使用hangfire等后台任务。您可以在Scott Hanselman的How to run Background Tasks in ASP.NET了解有关其他后台任务的更多信息。