繁体   English   中英

使用 Observable.Timer 安排异步作业/任务(并忽略异常)

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM