[英]Scheduling asynchronous jobs/tasks (and ignoring exceptions) using Observable.Timer
我有几个需要按计划运行的异步任务/作业,似乎我可以使用Observable
s 很好地做到这一点。 当作业获取数据时,可能会发生异常(例如 404),并且当处理结果数据时,也可能会发生错误。
我已经看到 Enigmativity 的这个答案,它似乎是包装IObservable<>
的完美解决方案,这样如果发生错误(当我获取数据时)我可以捕获它并继续(最终跳过该特定获取的处理)。
我知道当一个 Observable 错误意味着终止时,但鉴于我上面提到的答案,似乎有解决这个问题的方法,这将构成一个体面的作业调度系统。 欢迎使用其他方法,但我想了解如何使用 Observables 做到这一点。
我还想提供一些关于工作的 state 的反馈/记录。
目前,我有以下方法,无法编译!
job
是 object,其中包含有关作业的信息(例如作业运行列表及其结果/成功/失败、运行频率、状态、错误、boolean 指示作业是否应继续的标志等)
interval(job)
返回作业运行的频率(以毫秒为单位)
runSelect(job)
是一个 boolean 方法,它发出一个作业是否应该继续的信号(我认为用一个 observable 代替它会更好?当然还有使用 CancellationToken 的选项,但我再次不确定如何集成它!)
select(job)
是获取数据的方法
subscribe(job)
是处理数据的方法
public static IDisposable BuildObservable<TJob, TSelect>(TJob job, Func<TJob, int> interval, Func<TJob, bool> runSelect, Func<TJob, Task<TSelect>> select,
Func<TSelect, Task> subscribe)
where TJob : Job
where TSelect : class
{
return Observable.Timer(TimeSpan.Zero, TimeSpan.FromMilliseconds(interval(job)))
.SelectMany(x => Observable.FromAsync(async () =>
{
JobRunDetail jobRunDetail = job.StartNewRun();
if (runSelect(job))
{
jobRunDetail.SetRunningSelect();
return new { Result = await select(job), JobRunDetail = jobRunDetail };
}
else
{
jobRunDetail.SetAbandonedSelect();
return new { Result = (TSelect)null!, JobRunDetail = jobRunDetail };
}
}).ToExceptional())
.Subscribe(async (resultAndJobRunDetail) =>
{
//none of the resultAndJobRunDetail.Value.JobDetail or resultAndJobRunDetail.Value.Result statements will compile
resultAndJobRunDetail.Value.JobRunDetail.SetRunningSubscribe();
try
{
if (resultAndJobRunDetail.Value.Result!= null)
await subscribe(resultAndJobRunDetail.Value.Result);
resultAndJobRunDetail.Value.JobRunDetail.SetCompleted();
}
catch (Exception ee)
{
resultAndJobRunDetail.Value.JobRunDetail.SetErrorSubscribe(ee);
}
});
}
如前所述,resultAndJobRunDetail.Value.JobDetail 或 resultAndJobRunDetail.Value.Result 语句都不会编译,因为 resultAndJobRunDetail.Value 仍然是Observable<>
,但是当我删除.ToExceptional()
调用时,返回的值不再是Observable
. 显然我错过了一些东西。
我在 SO 上看到了使用Do()
而不是Subscribe()
的不同答案,所以我不确定哪个是合适的。 我还看到了建议使用Retry()
或“可观察到的错误处理方法”之一的答案,但我不确定如果我只想让我的工作无限重复,这些方法将如何工作?
最终,我仍在学习整个 Observable 基础设施如何组合在一起,所以我很可能完全偏离轨道!
在 Google 上搜索“使用 Observable 安排作业”毫无意义,因为 Observables 使用调度程序,所以毫无结果!
我不确定这是否有帮助,但是您的.ToExceptional()
调用位置错误:
public static IDisposable BuildObservable<TJob, TSelect>(TJob job, Func<TJob, int> interval, Func<TJob, bool> runSelect, Func<TJob, Task<TSelect>> select,
Func<TSelect, Task> subscribe)
where TJob : Job
where TSelect : class
{
return Observable.Timer(TimeSpan.Zero, TimeSpan.FromMilliseconds(interval(job)))
.SelectMany(x => Observable.FromAsync(async () =>
{
JobRunDetail jobRunDetail = job.StartNewRun();
if (runSelect(job))
{
jobRunDetail.SetRunningSelect();
return new { Result = await select(job), JobRunDetail = jobRunDetail }.ToExceptional();
}
else
{
jobRunDetail.SetAbandonedSelect();
return new { Result = (TSelect)null!, JobRunDetail = jobRunDetail }.ToExceptional();
}
}))
.Subscribe(async (resultAndJobRunDetail) =>
{
//none of the resultAndJobRunDetail.Value.JobDetail or resultAndJobRunDetail.Value.Result statements will compile
resultAndJobRunDetail.Value.JobRunDetail.SetRunningSubscribe();
try
{
if (resultAndJobRunDetail.Value.Result != null)
await subscribe(resultAndJobRunDetail.Value.Result);
resultAndJobRunDetail.Value.JobRunDetail.SetCompleted();
}
catch (Exception ee)
{
resultAndJobRunDetail.Value.JobRunDetail.SetErrorSubscribe(ee);
}
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.