【问题标题】:Background work in WCF Rest ServiceWCF Rest Service 中的后台工作
【发布时间】:2015-02-27 06:06:10
【问题描述】:

我有一个 WCF Rest 服务,它公开了一个 Web 方法,该方法应该启动一个长时间运行的进程,然后立即返回一个表示可用于跟踪任务状态的任务的 id。

[WebGet]
public Task<Guid> LongRunningProcess()
{
    var taskId = new Guid();

    var task = Task.Factory.StartNew(() =>
    {
        //Perform long running task
    }

    task.ContinueWith(task =>
    {
        //Send a notification to the client that the task has completed.
    }

    return taskId;
}

我的问题是,这是正确的做法吗?还是有更好更轻量级的方法?

【问题讨论】:

  • 您使用的是什么版本的 .NET?

标签: c# wcf rest asynchronous task


【解决方案1】:

我的理解是,如果您的工作受 CPU 限制,那么您最好同步执行工作。使用您的方法,请求将被停放,原始请求线程将被释放,但随后会将工作移交给另一个线程,并且在该线程完成之前请求不会完成。您不妨在原始线程中完成工作。

如果您有一些 IO,则将其设为异步是有意义的,因为异步 IO 不使用线程,它会释放您的请求线程来处理其他请求,从而提高您的可伸缩性。

更新

我认为您采用的方法很好,但鉴于您使用的是 .NET 4.5,我会使用 async-await,因为它会产生更简单的代码。然后我将使用 IO 操作的异步 API 和 await 其结果。例如:

[WebGet]
public async Task<Guid> LongRunningProcess()
{
    var taskId = new Guid();

    // IO bound operation
    var dbResult = await readFromDbAsync();

    // IO bound operation
    var dbResult = await readFromDbAsync();

    // CPU bound?
    generateReport(dbResult);

    // IO bound operation
    await sendNotification();

    return taskId;
}

如果你不熟悉async-await,我已经写了一个介绍here

【讨论】:

  • 谢谢。该操作从数据库中读取数据并生成一份报告,该报告被保存到磁盘中。一旦通知客户报告已准备就绪,他们就可以再次调用以检索报告。在这种情况下,上面的代码会达到这个目的吗?我有很多客户能够调用此方法并开始制作一份或多份报告。换句话说,客户可能会多次调用此方法,他们希望查看的每个报告一次,并且您可能有很多客户这样做。
  • 稍后我想添加请求队列,但我稍后会谈到,现在我正在尝试了解如何在后台简单地生成每个报告,以便服务可以处理许多请求并同时生成报告。
  • 感谢您的回答和代码示例。我实际上想要实现的是让服务方法启动一个长时间运行的进程(访问数据库、构建报告并将报告保存到磁盘)并立即返回一个 Id,我将其命名为 taskId,即用户可以使用它来跟踪报告的状态,并在以后通知它可以查看。方法中没有 await 是否意味着服务方法在报告完成之前不会返回,而不是立即返回任务 ID?再次感谢。
  • 没错,使用async 执行此操作可能不是最好的方法。看到这个问题stackoverflow.com/a/19918929/1239433
【解决方案2】:

您在那里勾画的内容(稍作修正)是一种实现您想要做的事情的方法。更难的部分是客户端的通知(我们成功使用 SignalR 集线器这样做,但具体机制取决于您)。

我谈到的小修正是,您的方法的返回类型应该只是上面代码中的Guid

一些注意事项: 在性能方面,TPL 可以很好地扩展(IMO),但在更大的范围内,您可能希望能够将长时间运行的任务分配到多个服务器等......

对于这种情况,我建议您查看非常适合此类用例的分布式作业队列(例如 Resque,存在 .NET 端口)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-05
    • 1970-01-01
    • 2011-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多