运行 作为 Quartz.NET 作业和处理对象问题的异步方法
Running a async method as a Quartz.NET job and disposed object issue
我在这种情况下使用 Quartz.NET(需要说明 GrabberContext
是 DbContext
扩展 class):
// configuring Autofac:
var builder = new ContainerBuilder();
// configuring GrabberContext
builder.RegisterType<GrabberContext>()
.AsSelf()
.InstancePerLifetimeScope();
// configuring GrabService
builder.RegisterType<GrabService>()
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
// configuring Quartz to use Autofac
builder.RegisterModule(new QuartzAutofacFactoryModule());
builder.RegisterModule(new QuartzAutofacJobsModule(typeof(DiConfig).Assembly));
var container = builder.Build();
// configuring jobs:
var scheduler = container.Resolve<IScheduler>();
scheduler.Start();
var jobDetail = new JobDetailImpl("GrabJob", null, typeof(GrabJob));
var trigger = TriggerBuilder.Create()
.WithIdentity("GrabJobTrigger")
.WithSimpleSchedule(x => x
.RepeatForever()
.WithIntervalInMinutes(1)
)
.StartAt(DateTimeOffset.UtcNow.AddSeconds(30))
.Build();
scheduler.ScheduleJob(jobDetail, trigger);
这就是工作:
public class GrabJob : IJob {
private readonly IGrabService _grabService;
public GrabJob(IGrabService grabService) { _grabService = grabService; }
public void Execute(IJobExecutionContext context) {
_grabService.CrawlNextAsync("");
}
}
GrabService
实现是这样的:
public class GrabService : IGrabService {
private readonly GrabberContext _context;
public GrabService(GrabberContext context) {
_context = context;
}
public async Task CrawlNextAsync(string group) {
try {
var feed = await _context.MyEntities.FindAsync(someId); // line #1
// at the line above, I'm getting the mentioned error...
} catch(Exception ex) {
Trace.WriteLine(ex.Message);
}
}
}
但是当执行到 line #1
时,我得到这个错误:
The ObjectContext instance has been disposed and can no longer be used
for operations that require a connection.
有什么想法吗?
您正在从同步方法 Execute()
调用异步方法 CrawlNextAsync()
。一旦 CrawlNextAsync()
击中 ...await _context
...,它会 returns,然后 Execute()
然后 returns,我假设此时 GrabJob
,因此 GrabService
,因此 GrabberContext
,被释放,而 CrawlNextAsync()
中的延续继续(并尝试使用已释放的 GrabberContext
)。
作为简单的修复,您可以尝试更改
public void Execute(IJobExecutionContext context) {
_grabService.CrawlNextAsync("");
}
至
public void Execute(IJobExecutionContext context) {
_grabService.CrawlNextAsync("").Wait();
}
我在这种情况下使用 Quartz.NET(需要说明 GrabberContext
是 DbContext
扩展 class):
// configuring Autofac:
var builder = new ContainerBuilder();
// configuring GrabberContext
builder.RegisterType<GrabberContext>()
.AsSelf()
.InstancePerLifetimeScope();
// configuring GrabService
builder.RegisterType<GrabService>()
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
// configuring Quartz to use Autofac
builder.RegisterModule(new QuartzAutofacFactoryModule());
builder.RegisterModule(new QuartzAutofacJobsModule(typeof(DiConfig).Assembly));
var container = builder.Build();
// configuring jobs:
var scheduler = container.Resolve<IScheduler>();
scheduler.Start();
var jobDetail = new JobDetailImpl("GrabJob", null, typeof(GrabJob));
var trigger = TriggerBuilder.Create()
.WithIdentity("GrabJobTrigger")
.WithSimpleSchedule(x => x
.RepeatForever()
.WithIntervalInMinutes(1)
)
.StartAt(DateTimeOffset.UtcNow.AddSeconds(30))
.Build();
scheduler.ScheduleJob(jobDetail, trigger);
这就是工作:
public class GrabJob : IJob {
private readonly IGrabService _grabService;
public GrabJob(IGrabService grabService) { _grabService = grabService; }
public void Execute(IJobExecutionContext context) {
_grabService.CrawlNextAsync("");
}
}
GrabService
实现是这样的:
public class GrabService : IGrabService {
private readonly GrabberContext _context;
public GrabService(GrabberContext context) {
_context = context;
}
public async Task CrawlNextAsync(string group) {
try {
var feed = await _context.MyEntities.FindAsync(someId); // line #1
// at the line above, I'm getting the mentioned error...
} catch(Exception ex) {
Trace.WriteLine(ex.Message);
}
}
}
但是当执行到 line #1
时,我得到这个错误:
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
有什么想法吗?
您正在从同步方法 Execute()
调用异步方法 CrawlNextAsync()
。一旦 CrawlNextAsync()
击中 ...await _context
...,它会 returns,然后 Execute()
然后 returns,我假设此时 GrabJob
,因此 GrabService
,因此 GrabberContext
,被释放,而 CrawlNextAsync()
中的延续继续(并尝试使用已释放的 GrabberContext
)。
作为简单的修复,您可以尝试更改
public void Execute(IJobExecutionContext context) {
_grabService.CrawlNextAsync("");
}
至
public void Execute(IJobExecutionContext context) {
_grabService.CrawlNextAsync("").Wait();
}