我正在开发一个与web服务通信的应用程序。客户端应用程序( silverlight-4.0)将调用web服务并触发一个长期运行的任务。因为完成任务需要一些时间,所以它是在一个单独的线程中执行的。(使用System.Threading.Tasks.Task.Factory.StartNew()创建单独的任务。)启动任务后,服务调用将返回一个ID,并完成连接。
这个ID应该是我需要识别任务的东西,这样我才能与它通信。
下一个调用(可能使用另一个连接)将被执行,以检查任务是否已经完成。为此,ID是调用的一部分。在服务器上,现在需要检查任务是否仍在运行或是否已完成。我怎么再找这个任务?
该服务在Azure上运行,由于负载平衡,第二个调用可能位于一个完全不同的系统上。在我看来,这是不可能的,但话说回来.
这个Q与这个Q有关。
发布于 2011-07-14 14:56:14
正确的方法是使用基于队列的通信。其原因是可伸缩性。您希望您的服务的“实例”获取请求,并且希望“一个实例”将结果返回给客户端,对吗?
你可以快速浏览一下我的博客中关于AppFabric队列的一篇文章,但是它们太大了。我就是这样做的:
创建一个WorkerRequest类,如下所示
public class WorkerRequest {
string clientId;
MyTaskEnum taskToPerform;
}写入队列存储,(在我的生产代码中,我使用的包装器还没有在博客上写,但计划: ),添加请求。
让工作线程侦听此队列,当收到请求时,生成一个新线程来完成它。完成后,将任务和客户端id作为您的密钥写入表存储。这样,您就可以始终检查状态(对表的简单/GET/请求)+您已经解决了解耦和可伸缩性问题。
希望能帮上忙。
更新:想解释得更多一些,所以我决定更新post =)
您可以在"web角色“中创建WCF web服务,这就是我要做的。我很久以前就博文了。在同一个角色中,您可以创建一个Worker。您可以通过拥有一个实现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()
{
}
}您只需在运行过程中实现一个while(true)循环,该循环将询问队列中是否有任何要处理的新消息。当收到这样的消息时,不要生成新的,只需处理它。如果您想要扩展它,可以通过添加新实例进行扩展。现在显然,这可能是昂贵的,所以实际上它是明智的产生一个新的线程,但只有一定的限制,例如最多5个线程。如果您的池中没有线程,则将消息返回到队列中(处理完消息后需要调用Complete(),否则不一定会被删除)。它稍后会被捡起来,或者被另一个工人捡起来。
因此,当工作线程完成后,将结果写入表存储,您就完成了。
发布于 2011-07-14 09:03:38
让任务在表存储/ appfabric缓存中报告其状态。然后,当有人轮询状态时,只需从所使用的持久性机制中读取任务ID X的相应状态。
发布于 2011-07-14 09:04:13
任务只需要在它已经完成的某个地方持久化,并在预期结果的情况下存储结果。
您可以在任何可用的表存储或SQL中使用任务ID存储完成。随后的轮询,以确定它是否已经完成,可以只检查这个存储并返回它是否完成。
解决此问题的另一种方法是让长期运行的任务在worker角色中运行。如果这个工作者角色公开了一个内部端点,那么任何一个web角色都可以询问该工作人员角色是否已经完成。
https://stackoverflow.com/questions/6690738
复制相似问题