跟踪进度(翻译地不好)¶

跟踪任务有两种方法:轮询和推送。轮询很容易理解,但推送是一种更舒适的方式,因为它可以避免对服务器的不必要的调用。此外, SignalR 大大简化了推送。

我会给你一个简单的例子,客户端只需要检查一个任务的完成情况。您可以在 Hangfire.Highlighter 项目中看到完整的示例。

Highlighter有以下后台任务,通过调用外部的web服务来突出代码的执行程度:

  1. public void Highlight(int snippetId)
  2. {
  3. var snippet = _dbContext.CodeSnippets.Find(snippetId);
  4. if (snippet == null) return;
  5.  
  6. snippet.HighlightedCode = HighlightSource(snippet.SourceCode);
  7. snippet.HighlightedAt = DateTime.UtcNow;
  8.  
  9. _dbContext.SaveChanges();
  10. }

轮询工作状态¶

举一个足够简单的例子,任务未完成意味着什么?意味着 HighlightedCode 属性 为空 。任务已完成又意味着什么?意味着指定的属性 有值

所以当还没执行到对应的代码时,我们需要在任务完成之前写一个JavaScript脚本来定时使用ajax访问控制器, 获取任务的状态(完成与否)。

  1. public ActionResult CheckHighlighted(int snippetId)
  2. {
  3. var snippet = _db.Snippets.Find(snippetId);
  4.  
  5. return snippet.HighlightedCode == null
  6. ? new HttpStatusCodeResult(HttpStatusCode.NoContent)
  7. : Content(snippet.HighlightedCode);
  8. }

当执行到对应的代码片段时,我们可以停止轮询。但是如果要跟踪工作的进度,您需要执行额外的步骤:

  • 添加 Status 字段到 snippets 表。
  • 在后台任务执行期间更新此字段。
  • 在轮询操作中检查该字段。
    但是有一个更好的方法。

使用SignalR推送¶

为什么我们需要轮询我们的服务器?因为它可以代表代码执行到哪里。 而我们也可以使用 SignalR, 一个了不起的推送利器。如果您不了解这个工具,我相信您在了解后一定会喜欢的。

我不想在这里列出所有的代码(你可以看一下下面这个例子的代码). 我只指出需要知道的两处不同,就可以发现十分简单。

First, you need to add a hub:

  1. public class SnippetHub : Hub
  2. {
  3. public async Task Subscribe(int snippetId)
  4. {
  5. await Groups.Add(Context.ConnectionId, GetGroup(snippetId));
  6.  
  7. // 当执行到对应的代码就会触发订阅
  8. // 我们只需马上推送
  9. // 否则会不停地监听
  10. using (var db = new HighlighterDbContext())
  11. {
  12. var snippet = await db.CodeSnippets
  13. .Where(x => x.Id == snippetId && x.HighlightedCode != null)
  14. .SingleOrDefaultAsync();
  15.  
  16. if (snippet != null)
  17. {
  18. Clients.Client(Context.ConnectionId)
  19. .highlight(snippet.Id, snippet.HighlightedCode);
  20. }
  21. }
  22. }
  23.  
  24. public static string GetGroup(int snippetId)
  25. {
  26. return "snippet:" + snippetId;
  27. }
  28. }

其次,您需要对后台任务的方法做一个小的改动:

  1. public void HighlightSnippet(int snippetId)
  2. {
  3. ...
  4. _dbContext.SaveChanges();
  5.  
  6. var hubContext = GlobalHost.ConnectionManager
  7. .GetHubContext<SnippetHub>();
  8.  
  9. hubContext.Clients.Group(SnippetHub.GetGroup(snippet.Id))
  10. .highlight(snippet.HighlightedCode);
  11. }

就这样!当用户打开对应的页面时,他的浏览器连接到服务器,订阅通知并等待更新通知。当后台任务即将完成时,它会将对应的信息发送给所有订阅的用户。

这样如果要跟踪进度,不需要额外的表和字段,只需要使用JavaScript。这是ASP.NET应用程序真正可靠的一个异步通讯例子,同时不需要太多的操作。

原文:

http://hangfirezh.zhs.press/background-processing/tracking-progress.html