2010-08-31 96 views
3

长职位..对不起调用webservice的异步

我一直在这读了,现在试图来回几天不同的解决方案,但我不能找到最明显的选择。我的困境。

关于我的情况;我向用户展示一个页面,该页面将包含几个不同的中继器,这些中继器显示一些基于来自几个Web服务调用的结果的信息。我希望将数据带入一个updatepanel(这将每隔两到三秒查询一次结果表,直到找到结果),所以我实际上想渲染页面,然后当数据是“准备就绪“就会显示出来。

该页面向控制器要求呈现的信息,并且控制器检查结果表以查看是否有任何可找到的东西。如果没有找到特定数据,它会调用WebServiceName.cs中的方法GetData()。 GetData不会返回任何东西,而是应该启动一个从web服务获取数据的异步操作。控制器返回null,并且UpdatePanel等待下一个查询。

当该操作完成时,它会将数据存储在数据库的相关位置,控制器在下一次请求时会找到它。

我现在的解决方案是启动另一个线程。我将举办页上的共享Web服务器,我不知道这是否会造成任何问题..

所以它驻留在page.aspx当前代码:

Thread t = new Thread(new ThreadStart(CreateService)); 
     t.Start(); 
    } 

    void CreateService() 
    { 
     ServiceName serviceName = new ServiceName(user, "12345", "MOVING", "Apartment", "5100", "0", "72", "Bill", "rate_total", "1", "103", "serviceHost", "password"); 

    } 

起初我还以为解决方案是使用Begin [Method]和End [Method],但似乎没有生成这些。我认为这似乎是一个很好的解决方案,所以当他们没有出现时我有点沮丧..有没有机会在添加Web引用时错过复选框或其他东西?

我不想使用[方法]异步,因为这会停止从渲染页面,直到[方法] AsyncCompleted被我所了解的内容调用。

我要做的调用不是CPU密集型的,我只是坐在慢速服务器上的webService上,所以我从这篇文章中了解到:http://msdn.microsoft.com/en-us/magazine/cc164128.aspx使线程池变大并不是一种选择,这实际上会降低性能(因为我不能投入硬件)。

您认为对我目前的情况来说最好的解决方案是什么?我真的不喜欢当前的(只有内心的感觉,但无论如何)

感谢您阅读这个相当长的帖子..

回答

2

有趣。直到你的问题,我不知道VS添加Web引用时,从使用Begin/EndAsync/Completed。我认为他们也会包括Begin/End,但显然他们没有。

你声明“GetData不会返回任何东西,但应该启动一个从web服务获取数据的异步操作”,所以我假设GetData实际上阻塞,直到“异步操作”完成。否则,你可以同时调用它。

无论如何,有很简单的方法可以使这个工作(异步委托等),但他们消耗每个异步操作的线程,这不会扩展。

您是对的,Async/Completed将阻止异步页面。 (注意:我相信,他们会而不是阻止同步页面 - 但我从来没有尝试过 - 所以如果你使用的是非异步页面,那么你可以尝试)。他们“阻止”异步页面的方法包含在SynchronizationContext;特别是每个异步页面都有一个挂起的操作计数,该计数递增Async并在Completed之后递减。

你应该能够伪造这个数(注意:我还没有尝试过这个);)。刚刚替补默认SynchronizationContext,而忽略计数:

var oldSyncContext = SynchronizationContext.Current; 
try 
{ 
    SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); 
    var serviceName = new ServiceName(..); 
    // Note: MyMethodCompleted will be invoked in a ThreadPool thread 
    // but WITHOUT an associated ASP.NET page, so some global state 
    // might be missing. Be careful with what code goes in there... 
    serviceName.MethodCompleted += MyMethodCompleted; 
    serviceName.MethodAsync(..); 
} 
finally 
{ 
    SynchronizationContext.SetSynchronizationContext(oldSyncContext); 
} 

我写的处理临时更换的SynchronizationContext.Current作为Nito.Async库的一部分的类。使用这个类简化了代码:

using (new ScopedSynchronizationContext(new SynchronizationContext())) 
{ 
    var serviceName = new ServiceName(..); 
    // Note: MyMethodCompleted will be invoked in a ThreadPool thread 
    // but WITHOUT an associated ASP.NET page, so some global state 
    // might be missing. Be careful with what code goes in there... 
    serviceName.MethodCompleted += MyMethodCompleted; 
    serviceName.MethodAsync(..); 
} 

该解决方案确实消耗一个线程,只是等待操作完成。它只是注册一个回调,并保持连接打开,直到响应到达。

+0

谢谢,我真的很感激。我明天会试试这个。作为旁注,aspx页面不允许使用async“feature”来调用异步方法。至少不是在我的情况下,因为我得到一个运行时错误,说明这个方法被调用的时候。 – Phil 2010-08-31 22:58:10

+0

就这样,我得到了这个直线,我应该欺骗IIS渲染页面,即使它应该被阻止?听起来很有趣:) – Phil 2010-08-31 23:01:29

+0

是的;总结一下。 – 2010-09-01 04:32:01

1

你可以这样做:

var action = new Action(CreateService); 
action.BeginInvoke(action.EndInvoke, action); 

或使用ThreadPool.QueueUserWorkItem

如果使用Thread,请务必设置IsBackground=true

有关于火灾伟大的职位,并在http://consultingblogs.emc.com/jonathangeorge/archive/2009/09/10/make-methods-fire-and-forget-with-postsharp.aspx

+0

感谢您的宝贵建议,我会尽快尝试。你知道这个解决方案是否会成为高并发用户负载情况下的瓶颈? – Phil 2010-08-31 22:11:10

+0

这些选项将全部使用每个异步操作的一个线程。 – 2010-08-31 22:22:25

0

忘记线程我会鼓励一种不同的方法 - 一个不使用更新面板。更新面板需要加载整个页面,并通过网络传输 - 您只需要一个控件的内容。

考虑使用MVC平台进行稍微更加自定义的&优化方法。您的数据流可能如下所示:

  1. 对您的网页有原始请求会产生一个线程,该线程会熄灭并加热您的数据。
  2. 让“骨架”页面返回给您的客户端
  3. 在上述页面中,有一个JavaScript线程调用您的服务器询问数据。
  4. 使用MVC,有一个返回的局部视图,这是仅限于你感兴趣的控制的控制器动作。

这会降低你的服务器的负载(可以有退避算法),降低通过电话发送的信息量,并且仍然给予客户极佳的体验。

+0

我喜欢这种方法,但我厌倦了从MasterPages到MVC模型的开发成本,因为我还没有阅读或尝试过。我是否需要对解决方案进行全面改造才能使用asp.net mvc? – Phil 2010-08-31 22:09:39

+0

不幸的是,这将会是一个非常重要的开发成本。但是,至少在我看来,MVC似乎有点像在大多数情况下要走的路。这是非常有组织的,并使我认为开发更容易。 – 2012-05-04 18:31:01

1

尝试使用以下设置

[WebMethod] 
[SoapDocumentMethod(OneWay = true)] 
void MyAsyncMethod(parameters) 
{ 
} 

在您的Web服务

但要小心,如果你使用模拟,我们对我们身边的问题。

+0

我明白'你的网络服务',你说我应该修改Web服务方法?我对web服务没有任何控制权,我相信它是用php编写的,但我真的不知道。 – Phil 2010-09-01 13:24:56