如何在不等待的情况下等待其他服务在后台完成任务?

时间:2019-04-04 12:20:44

标签: c# asp.net-core entity-framework-core asp.net-core-webapi autodesk-forge

我正在创建一个ASP.NET Core WebApi,它使用Autodesk Model Derivative API将Revit文件转换为另一种文件格式。上传文件后,Autodesk API将在后台开始工作,可能需要几分钟才能完成其工作。

我想监视Autodesk API的状态,以了解转换是否已经完成并通知用户。我正在寻找一种最佳的方式来监视作业状态,而无需“等待”并使请求挂起几分钟。

我尝试仅异步运行任务而不等待结果。直到我想要在数据库上下文中更新一个值的时候,这一直有效,因为由于请求结束,该值已被删除。

我还研究了一些有关实施后台服务的选项,但是还没有找到一种清晰的方法。

public async Task<ActionResult<Response<JobResponse>>> UploadFile(string bucketKey, IFormFile file)
{
    // ....
    // File has been uploaded 
    Response<JobResponse> response
        = await NetworkManager.PostAsync<JobResponse>(URI.Job.Url, JsonConvert.SerializeObject(jobData));

    // The job has been created in the Autodesk API, so I create a record in my own database
    var job = new Job(urn, file.FileName);
    context.Jobs.Add(job);
    await context.SaveChangesAsync();

    // This method is what I want to do in the background 
    MonitorStatus(job);

    return Respond(response);
}

private async Task MonitorStatus(Job job)
{
    bool isDone = false;

    while (!isDone)
    {
        isDone = await IsDone(job.Urn);

        if (!isDone)
            await Task.Delay(10000);
    }

    string guid = await new JobRepository(job).GetGuid();

    // The line underneath throws an error because the context has been disposed
    (await context.Jobs.FindAsync(job.Id)).Finish(guid);
    await context.SaveChangesAsync();

    // ...
    // Notify the user
}

2 个答案:

答案 0 :(得分:2)

Model Derivative API中文件的翻译可归结为两个主要端点:

  • POST job用于触发翻译,并且
  • GET manifest用于获取翻译的清单(包括翻译仍在运行时的状态)

如果您自己进行HTTP请求,则可以轮询清单,直到看到翻译已完成。

如果您使用的是Forge .NET SDK,则可以使用Translate方法触发翻译,并使用GetManifest方法来轮询结果。

答案 1 :(得分:1)

我最终使用了Autodesk Forge的Webhook,该Webhook调用了一个端点,该端点通知用户转换已完成。该Webhook包含一个主体,其中包含有关已完成作业的信息,因此我可以相应地更新数据库。

此Webhook消除了我的MonitorStatus(job)方法的需要。

https://forge.autodesk.com/en/docs/webhooks/v1/tutorials/create-a-hook-model-derivative/