如何与后台任务进行通信?

时间:2011-07-14 08:56:37

标签: asp.net c#-4.0 azure asmx

我正在开发一个与Web服务通信的应用程序。客户端应用程序(silverlight-4.0)将调用Web服务并触发长时间运行的任务。因为任务完成需要一些时间,所以它在一个单独的线程中执行。 (使用System.Threading.Tasks.Task.Factory.StartNew()创建单独的任务。)启动任务后,服务调用将返回一个ID并完成连接。
这个ID应该是我需要识别任务的东西,所以我可以与它进行通信。

可能使用其他连接进行下一次调用,以检查任务是否已完成。为此,ID是呼叫的一部分。在服务器上,它现在需要检查任务是否仍在运行或是否已完成。如何再次找到此任务?


该服务在Azure上运行,并且由于负载平衡,第二次调用可能位于完全不同的系统上。在我看来,这不可能做到,但再次...... 此Q与this Q

相关

3 个答案:

答案 0 :(得分:4)

让任务在表存储/ appfabric缓存中报告其状态。然后当nsomeone轮询状态时,只需从使用的持久性机制中读取任务ID X的相应状态。

答案 1 :(得分:3)

这样做的正确方法是使用基于队列的通信。原因是可伸缩性。您希望服务的“实例”获取请求,并且您希望“实例”将结果返回给客户端吗?

您可以快速查看我的一篇关于AppFabric Queues的博客文章,但它们过于笨重。这就是我的意思:

创建一个WorkerRequest类,看起来像这样

public class WorkerRequest {
   string clientId;
   MyTaskEnum taskToPerform;
}

写入队列存储,(在我的生产代码中,我使用的是一个我还没有写过博客的包装器,但计划:)),添加请求。

让工作线程监听此队列,并在收到请求时,生成一个新线程来完成它。完成后,使用您的任务&写入表存储。客户端ID作为您的密钥。这样你就可以随时检查状态(一个简单的/ GET /请求到表)+你有解耦和&可扩展性已经解决了。

希望它有所帮助。

UPDATE:想要解释一下,所以我决定更新帖子=)

您可以在“Web角色”中创建WCF Web服务,这就是我要做的。我前一段时间blogged about。在同一个角色中,您可以创建工作人员。你通过一个实现RoleEntryPoint的类来做到这一点。此类(位于Microsoft.WindowsAzure.ServiceRuntime中)如下所示:

  public abstract class RoleEntryPoint
  {
    public virtual bool OnStart()
    {
      return true;
    }

    public virtual void Run()
    {
      Thread.Sleep(-1);
    }

    public virtual void OnStop()
    {
    }
  }

您只需在Run中实现while(true)循环,该循环会询问Queue是否有任何新消息需要处理。收到此类消息后不会生成新消息,只需处理即可。如果要缩放它,可以通过添加新实例进行缩放。显然,这可能是昂贵的,所以实际上产生新线程是明智的,但仅限于某个限制,例如,最多5个线程。如果池中没有线程,则将消息返回到队列(完成消息后需要调用Complete(),否则不一定会被删除)。它会在以后或其他工作人员接收。

因此,当工作线程完成时,将结果写入表存储,然后就完成了。

答案 2 :(得分:2)

任务只需要在某个地方保持已完成,并在预期结果时存储结果。

您可以将任务ID存储在表存储或SQL Azure中,无论您身在何处。后续轮询以查看是否已完成,只需检查此存储并返回是否已完成。

解决此问题的另一种方法是让长时间运行的任务以辅助角色运行。如果此工作者角色公开了内部端点,那么任何Web角色都可以询问工作者角色是否已完成。