【问题标题】:Async webmethod without timeout没有超时的异步网络方法
【发布时间】:2010-03-16 12:46:59
【问题描述】:

我需要一个调用 webmethod 的控制台应用程序。

必须是异步的,并且没有超时(我们不知道这个方法处理任务需要多少时间。

有没有好办法:

[WebMethod]
[SoapDocumentMethod(OneWay = true)]

??

【问题讨论】:

  • 您需要网络方法的响应吗?
  • 使用 ASMX Web 服务不是一个“好方法”,除非你被 .NET 2.0 卡住了。 Microsoft 现在将 ASMX Web 服务视为“传统技术”。所有新的 Web 服务开发都应使用 WCF 完成。
  • MSDN 中的一篇文章标记了关于 ASMX 是“遗留”的注释(而 MSDN 中关于 ASMX 的较新文章带有该注释)不会突然使 ASMX 变得更糟在它做什么。整个辩论充其量与 phenevo 的问题是正交的。
  • ASMX 在 .NET 4 中受支持,并且在可预见的未来将继续支持(根据 Microsoft 的说法;只需询问他们)。如果你不得不采取恐吓手段来销售 WCF,那就说明了 WCF。
  • 如果您需要响应,那么您就不想使用 OneWay,因为它无法获得响应——它是即发即弃的。有关详细信息,请参阅下面的答案。

标签: c# web-services


【解决方案1】:

如果需要结果,请勿使用单向

首先,如果您需要方法的响应,您不需要[SoapDocumentMethod(OneWay = true)]。此属性创建一个“即发即弃”调用,它永远不会将响应返回给校准器,并且必须返回void。相反,使用常规方法调用并将其称为异步。

一种或两种方法?

如果您使用的是 ASMX,有两种基本解决方案:一种方法超时时间很长,或者两种方法(如 @Aaronaught suggested above):一种启动操作并返回操作 ID,另一个传递 ID 并检索结果(如果可用)。

就我个人而言,在大多数情况下我不会推荐这种两种方法的方法,因为这会带来额外的复杂性,包括:

  • 需要更改客户端和服务器代码以支持两步调用
  • RequestResponse 这样的ASP.NET 内部对象是not available when called from a background task launched with ThreadPool.QueueUserWorkItem.
  • 如果每个请求涉及多个线程,则在繁忙的服务器上进行限制会变得更加困难。
  • 服务器必须挂起结果,直到客户端获取它们(或者您决定将它们丢弃),如果结果很大,这可能会占用 RAM。
  • 您无法将大型中间结果流式传输回客户端

确实,在某些情况下,2 方法方法可能会更好地扩展,并且对客户端和服务器之间断开的网络连接更具弹性。如果您需要在数小时后获取结果,则需要考虑这一点。但是你的操作只需要几分钟,你可以保证客户端将保持连接,考虑到 2 方法方法的额外开发复杂性,我认为只有在单一方法解决方案不使用时才使用它符合您的需求。

无论如何,解决方案需要两部分。首先,您需要从客户端异步调用该方法。其次,您需要延长客户端和服务器的超时时间。我在下面都介绍了。

异步调用 ASMX Web 服务

要从命令行应用程序异步调用 ASMX Web 服务,请查看从第 2 页开始的 this article。它展示了如何使用较新的 Event-Based Async Pattern 从 .NET 客户端应用程序异步调用 Web 服务.请注意,不再推荐使用 here 描述的旧 .NET 1.0 方法,它依赖于代理上的 BeginXXX/EndXXX 方法,因为 Visual Studio 的代理生成器不会创建这些方法。最好使用上面链接的基于事件的模式。

这是上面文章的摘录/改编,因此您可以了解所涉及的代码:

void KickOffAsyncWebServiceCall(object sender, EventArgs e)
{
    HelloService service = new HelloService();
    //Hookup async event handler
    service.HelloWorldCompleted += new 
        HelloWorldCompletedEventHandler(this.HelloWorldCompleted);
    service.HelloWorldAsync();
}

void HelloWorldCompleted(object sender,
                         HelloWorldCompletedEventArgs args)
{
    //Display the return value
    Console.WriteLine (args.Result);
}

延长服务器和客户端超时时间

为了防止超时,http://www.dotnetmonster.com/Uwe/Forum.aspx/asp-net-web-services/5202/Web-Method-TimeOut 很好地总结了如何调整客户端和服务器超时。您没有在问题中指定您是拥有服务器端方法还是仅拥有客户端调用,因此下面的摘录涵盖了这两种情况:

有两个设置 影响webservice调用超时 行为:

** ASP.NET webservice 的服务器端 httpruntime 超时 设置,这是通过配置 以下元素:

httpRuntime 元素(ASP.NET 设置架构)
http://msdn2.microsoft.com/en-us/library/e1f13641.aspx


executionTimeout="45"
....../>
配置>

另外,请确保您已设置 以便 使超时正常工作。

** 如果您使用生成的 wsdl.exe 或 VS IDE “添加 webreference” 调用网络服务方法的代理, 还有一个超时设置 客户端代理类(派生自 SoapHttpClientProtocol 类)。这是 派生自的“超时”属性 “WebClientProtocol”类:

WebClientProtocol.Timeout 属性http://msdn2.microsoft.com/en-us/library/system.web.services.protocols.webclientprotocol.timeout.aspx

因此,您可以考虑调整 这两个值根据您的 应用的场景。这里有一个 以前的帖子也提到了这一点:

http://groups.google.com/group/microsoft.public.dotnet.framework.webservices/browse_thread/thread/73548848d0544bc9/bbf6737586ca3901

请注意,我强烈建议您将超时设置为足够长以包含您最长的操作(加上足够的缓冲区以确保事情变慢时的安全),但我不建议完全关闭超时。允许无限超时通常是不好的编程习惯,因为错误的客户端或服务器可以永久禁用另一个。相反,只需将超时设置得很长 --- 并确保记录客户端或服务器超时的实例,以便在问题发生时检测和诊断问题!

最后,回应上面的评论:对于新代码,最好使用 WCF。但是,如果您在使用 ASMX Web 服务时遇到问题,上述解决方案应该可以工作。

【讨论】:

    【解决方案2】:

    如果方法实际上是单向的,并且您不关心结果或需要跟进请求的状态,那么这就足够了。

    如果您确实需要一个结果(最终),或者需要检查操作的状态,那么这将不会很好地工作。在这种情况下,您的方法应该做的是在后台线程中开始工作,然后立即返回一个 ID,该 ID 可用于不同的 Web 方法来查找状态。

    所以是这样的:

    public enum JobStatus { Running, Completed, Failed };
    
    public class MyService : WebService
    {
        [WebMethod]
        public int BeginJob()
        {
            int id = GetJobID();
            // Save to a database or persistent data source
            SaveJobStatus(id, JobStatus.Running);
            ThreadPool.QueueUserWorkItem(s =>
            {
                // Do the work here
                SaveJobStatus(id, JobStatus.Completed);
            }
            return id;
        }
    
        [WebMethod]
        public JobStatus GetJobStatus(int id)
        {
            // Load the status from database or other persistent data source
            return ( ... )
        }
    }
    

    这是开始工作的一种方法,也是检查其状态的另一种方法。由客户端定期轮询。这不是一个很好的系统,但你没有很多使用 ASMX 的选择。

    当然,如果您确实需要此操作的响应,更好的方法是改用 WCF。 WCF 为您提供callback contracts,您可以使用它来开始单向操作并在该操作完成时订阅通知,这样就无需进行上述轮询。

    所以,总结一下:

    • 如果您不需要任何响应或状态更新,只需使用IsOneWay = true

    • 如果您确实需要更新,并且可以在服务端使用 WCF,请将其与回调合同一起使用。无论如何,您都应该将 WCF 用于新的 Web 服务项目。

    • 如果您需要更新但无法使用 WCF,请在后台线程中执行工作并使用附加的状态检查 Web 方法实现定期轮询系统。

    【讨论】:

      猜你喜欢
      • 2018-05-21
      • 1970-01-01
      • 1970-01-01
      • 2020-05-30
      • 1970-01-01
      • 2017-07-22
      • 1970-01-01
      • 1970-01-01
      • 2012-07-19
      相关资源
      最近更新 更多