|
|
1
8
杰夫,我不完全确定你是如何模拟连接故障的。我假设“好像服务器不响应”意味着您正在寻找某种超时错误。您可能通过在服务器端使用thread.sleep()强制服务调用的慢响应来模拟非响应服务器。正确的?足够接近吗? 我有一个类似的项目,所以我测试了它,并成功地捕获了超时和其他异常。我认为您可能没有看到这些异常,因为您的自定义绑定有很长的默认超时时间,并且您可能没有等待足够长的时间。 解释一下,WCF超时由绑定配置控制。查看代码后,您将创建自己的自定义绑定,如下所示:
如果在那里设置一个断点并检查您创建的自定义绑定,您将看到它有一分钟的时间。 SendTimeout 默认情况下。我怀疑您没有等待足够长的时间,或者没有将服务的模拟超时设置足够长的时间,所以您无法捕获超时异常。 下面是一些需要演示的代码更改。首先,要设置绑定的超时:
最后,要捕获异常并引发正确的事件,可以按如下方式更新AsyncCallback委托。调用endget()时引发异常。
对于一般的代码审查,我建议您避免对绑定配置进行硬编码。相反,您可以在servicereferences.clientconfig文件中声明端点配置(包括合理的超时),并使用以下端点名称新建通道工厂:
这将使应用程序随着时间的推移更易于维护。 我希望这有帮助。 杰瑞 更新: 杰夫 请看一下这段代码和里面的注释,了解更多关于这里发生的事情的解释。makeCall()方法正在创建传递给beginget()方法的函数(委托)。该功能稍后在服务响应时执行。 请进行建议的更改,并在以“asyncCallback asyncCallback”和“var items”开头的行设置断点。您将看到,第一次通过调试器仅仅声明了当服务响应时要执行的代码(函数/委托),第二次通过是该响应的实际处理,从委托声明的内部开始。这意味着当处理服务调用的响应时,外部try/catch将不在范围内。
杰瑞 |
|
|
2
4
我以前也遇到过类似的问题。主要问题在于如何在代理/通道的实例上实现IDisposable。我解决它的方法显示在下面的代码中,其中
使用上述类的方法如下:
因为
请阅读以下日志以了解更多信息,并了解以上代码的更通用版本: http://bloggingabout.net/blogs/erwyn/archive/2006/12/09/WCF-Service-Proxy-Helper.aspx |
|
|
3
0
为了捕获与服务器的通信错误,我建议将呼叫
另外,一般性建议中最重要的一点是:创建channelFactory是一项非常昂贵的操作,因此您可能希望单独执行此操作,并将对channelFactory对象的引用存储在某个地方。 如果您需要从ChannelFactory创建并可能重新创建通道,那么您可以反复使用ChannelFactory的存储/缓存实例,而无需一直创建该实例。 但除此之外,我认为你在这里做得很好! 马克 |
|
|
4
0
当超时发生时,ChannelFactory实例将处于“已中止”状态。您将发现,不是在调用中发生异常时引发异常,而是在调用_channel.dispose()时引发异常。 你需要以某种方式防范这个例外。最简单的方法是在Dispose方法的内容周围放置一个Try/Catch,但最好在尝试关闭/Dispose之前检查通道实例的状态。 这就是为什么你仍然得到例外-它不是在这里处理。 更新: 根据堆栈跟踪,框架似乎正在尝试执行回调委托,并在那里遇到异常。你在其他地方回答说,试图/捕捉你的代表的内容并不能解决问题…内部异常呢?exception.toString()的完整输出是什么? 我浏览了.NET框架,它确实可以一直返回到threadpool(至少在stacktrace中是这样),这将导致未处理的异常和线程死亡。如果情况变得更糟,您可以随时接管线程…旋转您自己的线程并在内部同步调用服务,而不是使用内置异步模式(除非这是一种WCF双工通信类型,我认为这不是)。 我仍然认为完整的异常信息(如果还有其他信息的话)可能有用。 |
|
|
5
0
杰夫,请给我们看看 你的 尝试在endget调用周围放置try/catch块时的代码。很难相信这没有抓住一个例外,看到它会帮助我相信。 另外,作为这个实验的一部分,去掉unhandledException事件处理程序。我想只要browserhttprequest意识到有404,你就会发现这个异常。我认为,如果没有unhandledException事件,endget周围的try/catch将捕获异常(如果有)。我认为您正在获取异常处理过程的中间状态。 我还希望看到您在endget调用后立即放置System.Debugger.Break或其他东西。 |
|
|
6
0
我认为你设计了你的
如果是,那就是问题所在。WCF通道类的设计使得编写完全满足所有可能的错误条件的通用处理代码变得非常困难。如果它很简单,那么通道类本身就可以安全地进行释放,而您不需要包装类。 迄今为止,我找到的唯一安全的方法是不封装Dispose逻辑,而是封装整个调用序列,因此:
我知道这是同步调用,但原理是一样的。而不是你试图推断你是否应该打电话给
注-只有实际的通道需要这种特殊处理。你可以随意处置工厂。 |
|
|
7
0
我认为问题在于您设计服务调用程序的方式。 创建服务调用方时,将打开通道。这意味着通道可以超时,并且您的代码中没有任何可以从超时恢复的内容。 我会将通道的创建和关闭移动到make call方法。 您可以围绕begin-get和回调内容执行一个try-catch。 |