2011-07-14 26 views
1

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

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


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

回答

3

这样做的正确方法是使用基于队列的通信。原因是可扩展性。你想让你的服务的“实例”接收请求,并且你希望“一个实例”将结果返回给客户端吗?

您可以快速浏览一下我的关于AppFabric Queues的博客文章,但它们太笨重了。下面是如何I'do它:

创建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() 
    { 
    } 
    } 

您简单地实现在运行一段时间(true)循环,询问队列是否有用于处理任何新的消息。当收到这样的消息不会产生一个新的,只是处理它。如果您想缩放它,可以通过添加新实例进行缩放。显然,这可能是昂贵的,所以实际上产生新线程是明智的,但仅限于某个极限,例如,最多5个线程。如果池中没有线程,则将消息返回队列(当您完成消息时,您需要调用Complete(),否则它不一定会被删除)。它会在稍后或另一名工作人员中被拾起。

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

4

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

+0

+1两个答案 - 同一个想法在同一时间。在极端情况下 - 客户端和服务器之间需要真正紧密的耦合 - 那么您也可以使用粘滞会话模式 - http://dunnry.com/blog/2010/10/14/StickyHTTPSessionRoutingInWindowsAzure.aspx - 但这不适用于简单情况下(IMO) – Stuart

+0

我必须诚实地说,马丁巴比我快了4秒。 –

+0

表存储/ appfabric缓存的使用是诱人的,并会简化大部分的轮询。但大卫斯蒂尔建议的工作者角色听起来也很有趣... –

2

该任务只需要在某处完成并保存结果,如果结果是预期的。

您可以在任何可用的位置存储带有任务ID的完成和表存储或SQL Azure。后续轮询以查看它是否完成可以检查该存储并返回它是否完成。

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

+0

工人角色?嗯...有趣的概念。没有想过这些。 –

+0

如果任务长时间运行,但不是太CPU或IO密集,那么你可以在你的web角色的单独线程中运行它们并节省资金。如果他们是勤奋的工作,那么最好将他们推到一个单独的工作者角色中,以免对您的网络角色产生不利影响。 –

相关问题