- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在研究一种使用 ContinueWith 来完成以下任务的方法:
我遇到的是太多事件部件。原始应用程序是 C#/MVC 应用程序。用户做他的事,最后提交一个长时间运行的作业来执行。作业处理器(C# 库)会做一些工作,然后调用 JAVA SOAP 端点来传递初始处理的结果。 JAVA SOAP 端点调用 COTS 应用程序来执行处理的首当其冲,然后用“我完成了”回调作业。
如您所见,我没有明确的方法来执行以下操作:
var parentId = _jobs.Enqueue<MyJob>(x => x.StartExecution(job.Id));
_jobs.ContinueWith<JAVA_ENDPOINT>(parentId, x => x.JAVA_EXECUTION(job.Id)); // this part is not in my control!
_jobs.ContinueWith<MyJob>(parentId, x => x.ContinueExecution(job.Id));
我确实有一个 REST 服务 (POST),我正在使用它作为开始工作的唯一方式。基本上,传递一个格式良好的有效负载(JSON), Controller 从 IoC 容器中选择作业对象,决定它是哪种类型的作业(临时、重复、连续等),然后执行正确的 Hangfire 调用以入队它。 JAVA 端点也可以轻松调用此 REST 服务。
[HttpPost]
public string Post()
{
// safety checks removed for brevity...
var command = new MinimumCommandModel(Request.Content.ReadAsStringAsync().Result);
return GetPostPipeline().Handle(command).Id;
}
private static IRequestHandler<MinimumCommandModel, MinimumResultModel> GetPostPipeline()
{
return new MediatorPipeline<MinimumCommandModel, MinimumResultModel>
(new QueuePostMediator()
, new IPreRequestHandler<MinimumCommandModel>[]
{
new PreJobLogger(),
new PreJobExistsValidator(),
new PreJobPropertiesValidator()
}
, new IPostRequestHandler<MinimumCommandModel, MinimumResultModel>[]
{
new PostJobLogger()
}
);
}
QueuePostMediator 处理作业类型的细节(AdHoc 等)。我现在正在尝试编写延续处理程序,但对如何进行此操作感到有点受阻。我当然不想在 Hangfire 之外进行任何类型的阻止操作。当原始作业最初未与原始作业的 parentId 连接时,我不确定如何“开始”另一项作业作为原始作业的延续。
基本上,如果我可以从工作内部暂停工作,直到外部刺激告诉 hangfire 继续工作,那我就是黄金了。不过,我还没有破解如何实现这一点。
想法?想法?
最佳答案
好的。我已经想出一个 hack 来让它工作。
我正在使用一种策略模式来运行每个作业的不同部分。我有一个名为 Handoff 的 JobStatus,现在执行此操作:
public class Processing : BaseJobExecutor<PayloadModel>, IJobExecutor<PayloadModel>
{
public Processing(JobPingPong job) : base(job, JobStatus.Processing) {}
public void Handle()
{
JobInfo.JobStatus = JobStatus.ExtProcessing;
JobInfo.HangfireParentJobId = JobInfo.HangfireJobId;
Payload.PostToQueueText(@"http://localhost:8080/api/clone");
// Pause the current job (this is the parent job) so the outside web service has a chance to complete...
var enqueuedIn = new TimeSpan(0, 6, 0, 0); // 6 hours out...
JobPutOnHold(JobInfo.HangfireJobId, enqueuedIn);
// The next status to be executed upon hydration...
JobInfo.JobStatus = JobStatus.Complete;
Job.CachePut();
// Signal the job executor that this job is "done" due to an outside process needing to run...
JobInfo.JobStatus = JobStatus.Handoff;
}
}
public void JobPutOnHold(string jobId, TimeSpan enqueuedIn)
{
var jobClient = new BackgroundJobClient();
jobClient.ChangeState(jobId, new ScheduledState(enqueuedIn));
}
现在,在策略执行器中我可以这样做:
public string Execute(IServerFilter jobContext, IJobCancellationToken cancellationToken)
{
while (Payload.JobInfo.JobStatus != JobStatus.Done)
{
cancellationToken?.ThrowIfCancellationRequested();
var jobStrategy = new JobExecutorStrategy<TPayload>(Executors);
Payload = jobStrategy.Execute(Payload);
if (Payload.JobInfo.JobStatus == JobStatus.Handoff)
break;
}
return PayloadAsString;
}
作业的第二部分与第一部分相同,但来自外部服务并具有 ExtComplete 状态,这允许作业根据来自外部世界的结果(存储在D B)。像这样:
public class ExtComplete : BaseJobExecutor<PayloadModel>, IJobExecutor<PayloadModel>
{
public ExtComplete(JobPingPong job) : base(job, JobStatus.ExtComplete) { }
public void Handle()
{
// do post processing here...
Payload.Tokens = null;
JobInfo.JobStatus = JobStatus.Complete;
if (JobInfo.HangfireJobId != JobContext.JobId || JobInfo.HangfireParentJobId == JobInfo.HangfireJobId)
{
JobInfo.HangfireParentJobId = JobInfo.HangfireJobId;
JobInfo.HangfireJobId = JobContext.JobId;
}
// Enqueue the previous (parent) job so it can complete...
JobExecuteNow(JobInfo.HangfireParentJobId);
}
}
public void JobExecuteNow(string jobId)
{
var enqueuedIn = new TimeSpan(0, 0, 0, 15);
var jobClient = new BackgroundJobClient();
jobClient.ChangeState(jobId, new ScheduledState(enqueuedIn));
}
最终,时间将由配置驱动,但现在我将其设置为让第一个作业在 15 秒内开始执行。
我面对这种方法的唯一挑战是进来的作业有效负载是在任何处理发生之前的原始有效负载。这就是为什么您会看到上面的“缓存”。当作业重新启动时,我检查是否存在该 Hangfire JobId 的缓存,如果存在,则从缓存中加载最后已知的有效负载,然后让执行程序继续其愉快的方式。
到目前为止效果很好。
注意:我仍在尝试学习如何更改/注入(inject) Hangfire 中的命令链和状态对象,以使其更适合 hangfire。我们有一份工作可以调用十几个或更多的外线电话。目前,运行大约需要 12 个小时。
关于c# - Hangfire ContinueWith 多个来源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39926207/
此处讨论的代码是用 C# 编写并使用 .netcore 3.1 执行 我有以下代码,它在后台启动工作负载而不等待它完成(即发即忘): public void StartBackgroundWork(I
我正在尝试记录对 API 的请求和响应。我目前正在使用一个 delegatingHandler 来捕获 httpwebresponses 和 httpwebrequests。 处理程序: pr
我遇到了以下我试图理解的异步代码(针对此示例进行了简化): class Program { static async Task Main(string[] args) {
我刚刚开始熟悉 Task Parallel Library,但有一个相当琐碎的问题,我无法找到明确的答案。 以下片段之间有什么区别,我应该在什么时候选择一个而不是另一个? Task t = Task.
我在一个很难重现的竞争条件下运行,从我的代码分析来看,它似乎来自一个不执行(或直到结束才执行)的延续。 这里是一些呈现上下文的伪代码: Task GetObject(string id) {
我看到了 Stephen Cleary 关于 Startnew being dangerous 的博客以及如何continuewith is also dangerous .我想在这里使用它来避免在出
我试图在这个例子中链接执行任务: static List clsTaskList = new List(); private static void Tasks2() { Task t1 =
我有以下代码(https://github.com/avinash0161/OrleansExperiments/tree/c0155b4b0c8c1bfe60aea8624f2cc83a52853d
我们的团队遇到了一个问题,即 ContinueWith() 在主机进程关闭之前不会运行。例如,下面的代码已经在生产环境中运行良好一年了。但是自从我们开始使用更新版本的框架后,我们就遇到了这个问题。 运
我在一堆 LINQ 查询上有一些 GUI。查询需要一些时间来执行,所以我希望 GUI 能够响应并显示繁忙指示器和进度条。许多查询是为了检查数据中存在的某些条件。如果查询返回空结果,应用程序应继续下一个
使用 Visual Studio 2015,针对 FW 4(在 FW 4 下测试不可观察的异常): 我期待这段代码: static void Main(string[] args) { try
如果这是一个简单的问题,请原谅我;我无法用足够通用的方式来表达它来搜索答案。 考虑这段代码: var task = Task.Factory.StartNew(() => Whatever());
使用什么值 ContinueWith(Action continuationAction)对于 CancellationToken , TaskContinuationOptions和 TaskSch
我有这个示例代码: static void Main(string[] args) { var t1 = Task.Run(async () => {
我有一些代码用作轻量级、非阻塞的关键部分。我希望无论 Task.Run 子句中的 _func 和 cancellationToken 发生什么情况,都能保证继续运行,这样finally block 中
我用这个代码 public static void Main() { Task t = new Task(() => { return 43; });
请看下面的代码- static void Main(string[] args) { // Get the task. var task = Task.Factory.StartNew
我有控制台应用程序和代码如下, 我的问题是在ContinueWith任务完成之前,控制台应用程序结束,它不等待continueWith完成,请指教。 请让我知道我遗漏了什么或不正确。 var task
我有以下代码,其中延续代码没有被执行。 using System; using System.Threading; using System.Threading.Tasks; namespace Ko
据我了解,ContinueWith 方法会等待相关任务完成。对于以下代码,这意味着它在完成子任务后就完成了。如果这是真的,为什么它有时会输出0 0 0 和其他时间 0 1 2? static
我是一名优秀的程序员,十分优秀!