0

我正在尝试创建一个执行 Sql 命令的计划任务。实际计划的过程工作正常,但是我的 dbcontext 存在无法实际访问数据库的问题。

它将获得一个包含所有适当表的上下文,但对表的任何操作都会引发InvalidOperationException. 当尝试在调试模式下检查任何表格元素时,它们也都InvalidOperationException以红色X作为图标。

我也尝试通过MediatR命令和处理程序发送命令,但错误相同。每次更改代码的尝试都会导致相同的错误而没有偏差。

这是我第一次尝试创建后台服务,作为参考,我正在学习 https://thinkrethink.net/2018/02/21/asp-net-core-background-processing/的教程

启动.cs

            // truncated
            services.AddDbContext<MyDbContext>();
            services.AddSingleton<IHostedService, Daily_Task>();

后台服务

namespace MyApi.ScheduledTasks
{
    public abstract class BackgroundService : IHostedService
    {
        private Task _executingTask;
        private readonly CancellationTokenSource tokenSource = new CancellationTokenSource();

        public virtual Task StartAsync(CancellationToken token)
        {
            _executingTask = ExecuteAsync(tokenSource.Token);

            return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask;
        }

        public virtual async Task StopAsync(CancellationToken token)
        {
            if (_executingTask == null)
                return;

            try
            {
                tokenSource.Cancel();
            }
            finally
            {
                await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite, token));
            }
        }

        protected virtual async Task ExecuteAsync(CancellationToken token)
        {
            do
                await Process();
            while (!token.IsCancellationRequested);
        }

        protected abstract Task Process();
    }
}

范围处理器

namespace MyApi.ScheduledTasks
{
    public abstract class ScopedProcessor: BackgroundService
    {
        private readonly IServiceScopeFactory _scopeFactory;

        public ScopedProcessor(IServiceScopeFactory scopeFactory)
        {
            _scopeFactory = scopeFactory;
        }

        protected override async Task Process()
        {
            using (var scope = _scopeFactory.CreateScope())
            {
                await ProcessInScope(scope.ServiceProvider);
            }
        }

        public abstract Task ProcessInScope(IServiceProvider provider);
    }
}

待安排的任务

namespace MyApi.ScheduledTasks
{
    public class Daily_Task : ScopedProcessor
    {
        private DateTime Start => DateTime.Now;

        private DateTime NextTask { get; private set; }

        public Daily_Task(IServiceScopeFactory scopeFactory) : base(scopeFactory) 
        {
            NextTask = SetNextRun(Start);
        }

        // currently doing minutes for testing
        private DateTime SetNextRun(DateTime date) => date.AddMinutes(1);

        public override async Task ProcessInScope(IServiceProvider provider)
        {
            try
            {
                using (var context = provider.GetRequiredService<MyDbContext>())
                {
                    // even this causes an error
                    var data = context.MyTable.Any();
                }
            }
            catch (Exception e)
            {
                Log.Error(e);
            }
            await Task.CompletedTask;
        }

        protected override async Task ExecuteAsync(CancellationToken token)
        {
            do
            {
                var now = DateTime.Now;
                if (now > NextTask)
                {
                    await Process();
                    NextTask = SetNextRun(now);
                }
            }
            while (!token.IsCancellationRequested);
        }
    }
}
4

1 回答 1

0

学习如何做后台服务很容易混淆,因为有关于如何做的教程,然后 .NET 在 dotnetcore 开发过程中添加和更改了使教程无效的最佳实践。现在有一个可以实现的 BackgroundService 基类,它应该使用 AddHostedService 添加到您的 DI 容器中。它在 Microsoft.Extensions.DependencyInjection 中已经有一段时间了。如果您改用它,它将大大简化您添加后台服务所要做的事情。

关于实现 BackgroundService 的快速入门:

仅覆盖 ExecuteAsync。主机将等待它返回,因此如果您有一个长时间运行的后台任务(或永久后台任务),那么您希望返回一个任务,而不是等待它从 ExecuteAsync 完成(例如:使用 Task.Run)。当应用程序被触发关闭时,传递给 ExecuteAsync 的取消令牌将被取消,您有几秒钟的时间在进程退出之前正常关闭。:P 默认情况下,不会为托管服务创建范围,因此您需要注入您已经知道如何操作的 IServiceProvider。

参考: https ://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.1&tabs=visual-studio

于 2020-01-23T21:09:49.603 回答