C# 关于超时和异常的奇怪WCF行为
我已经创建了一个承载在普通Windows服务中的WCF服务。此服务部署到客户并设置在他们的服务器上。因此(afaik)我需要动态地建立WCF代理,不能依赖VS或Silverlight工具创建的一些预构建代理。本例中的客户端是使用Xamarin.Forms构建的移动应用程序。C# 关于超时和异常的奇怪WCF行为,c#,wcf,xamarin.forms,C#,Wcf,Xamarin.forms,我已经创建了一个承载在普通Windows服务中的WCF服务。此服务部署到客户并设置在他们的服务器上。因此(afaik)我需要动态地建立WCF代理,不能依赖VS或Silverlight工具创建的一些预构建代理。本例中的客户端是使用Xamarin.Forms构建的移动应用程序。 创建“通道”的代码: public void Init(int timeout=15) { ea=新的端点地址(string.Format(“http://{0}:{1}/{2}”)、_-setingsService.Con
创建“通道”的代码:
public void Init(int timeout=15)
{
ea=新的端点地址(string.Format(“http://{0}:{1}/{2}”)、_-setingsService.ConnectionIP、_-setingsService.ConnectionPort、_-setingsService.ConnectionEndpoint);
bhttpb=新的BasicHttpBinding(BasicHttpSecurityMode.None);
bhttpb.SendTimeout=TimeSpan.FromSeconds(超时);
cfIMMC=新渠道工厂(bhttpb,ea);
cfIMMC.Opened+=cfIMMC_Opened;
cfIMMC.Faulted+=cfIMMC_Faulted;
cfIMMC.Closed+=cfIMMC_Closed;
immc=cfIMMC.CreateChannel(ea);
immc.Ping();//此函数由我在合同中定义。它仅返回true(如果可以访问服务器)。
}
到目前为止,如果服务正在运行,一切都正常,但应用程序必须“离线”运行,然后会变得很奇怪。当建立连接时,没有
EndpointException
或任何东西,当调用函数时,它只是坐在那里等待超时。如果能得到一些关于WCF服务是否真的存在的信息,那就太好了。我有可能需要几分钟的函数调用,如果应用程序在WCF服务器根本不存在的情况下等待那么长时间,那将是致命的。我怎样才能做到这一点 更新:
现在它变得更奇怪了。现在,大约。在
Ping()
失败30秒后,我得到了System.Net.Sockets.SocketException:Connection timed out
和System.Net.WebException:Error:ConnectFailure(Connection timed out)
更新2:
下面是调用堆栈的图片:
如果您需要有关服务是否处于活动状态的快速反馈,则设置其他端点(单独的合同仅包含
Ping
方法)并为其设置小的超时。
重要的部分是将发送/接收超时设置为较小的值-这将确保Ping
方法在服务不可用时快速返回/抛出
据我记忆所及,WCF在您调用其中一种方法之前不会打开通道(=不连接到服务器)-这就是为什么在调用Ping
之前不会出现异常
大约30秒后发生异常。你在哪里看到的?我的意思是,是VisualStudio在这里中断,还是应用程序因未处理的异常而失败?我这样问是因为我在Xamarin/Mono代码中看到了这一点:
initConn = new WaitCallback (state => {
try {
InitConnection (state);
} catch {}
});
这意味着即使这个异常在30秒后抛出,它也会被吞没。真正发生的情况是,当发送请求时(即调用Ping()
),运行时尝试在后台打开连接(您的调用堆栈确认了这一点),30秒是默认的Windows连接超时。如果WCF设置了较低的超时时间(如您的情况),则WCF将更早失败,但连接尝试将持续30秒,并将在异常情况下完成
因此,我的意见是,您不应该关心此异常,除非它以某种方式停止您的应用程序。问题是,我没有得到堆栈跟踪。它甚至没有在我的代码中显示一行。我唯一能提供的就是调用堆栈。我更新了我的问题。所以首先,我几乎按照你建议的方式解决了这个问题,但我是用同样的合同和另一个500毫秒定时的频道来解决的。第二,是VS打破了它,告诉我有一个例外。但现在我已经从VS15切换到了17,它不见了。(我怀疑某些异常设置是错误的)。第三,了解我们正在使用的框架的一些内部信息总是很好的,感谢您的洞察力。
initConn = new WaitCallback (state => {
try {
InitConnection (state);
} catch {}
});