我的WPF应用程序出现问题已经困难了几天,我想知道是否有人之前遇到过这个问题并且可以提供帮助?
问题似乎归结为客户端生成“即时”序列化程序来处理该Web方法调用中的类型。当第一次调用该方法时(Web服务本身已经运行),可能需要例如8秒,后续通话可能需要20毫秒。在此延迟期间,客户端WPF进程上的CPU为v。
使用XmlSerializer时,有一种方法可以使用svcutil预生成这些序列化程序集。当(正如我们)使用普通的WCF DataContractSerializer时,此选项似乎不存在。
我想要的是能够为我的所有数据合同(很多)中的所有类型预生成此程序集,或者替换为使用我可以编码的自定义程序替换此过程并以二进制形式传递数据(我们拥有这个webservice / client的两端,它们都是.NET 4)。我已经使用了BinaryForamtter和GZip压缩,虽然这加速了数据的传输,但它总是被恢复为XML以被框架反序列化,因此这个问题仍然存在。
有任何想法吗?
您可以使用二进制库,如 protobuf网,这是非常快的,即使有初始启动成本,因为必须为每种类型生成代码,它仍然是 比...更好的方式 DataContractSerializer
要么 BinaryFormatter
。您应该获得几秒钟,并获得整体更顺畅的体验。有可能 与WCF轻松集成。请记住,WCF仍将检查您的各种合同,以生成正确的WSDL和各种元数据。
还有其他因素可能会降低WCF启动速度,例如确定默认Web代理。确保这一点 useDefaultWebProxy
是 false
在您的绑定配置中,如果您没有任何用途。
不过,无论你采取什么措施来优化它,你都会发现WCF启动通常很慢。就个人而言,厌倦了类似场景中的缓慢战斗(我控制了两端,而客户端是一个WPF应用程序),我只是放弃了WCF并且去了 ServiceStack + protobuf-net。第一个呼叫从2-3秒到大约100毫秒,所有后续的HTTP呼叫都是瞬时的。整体用户体验大大提升。请注意,我与ServiceStack没有任何关系,这只是我的经验。
您可以使用二进制库,如 protobuf网,这是非常快的,即使有初始启动成本,因为必须为每种类型生成代码,它仍然是 比...更好的方式 DataContractSerializer
要么 BinaryFormatter
。您应该获得几秒钟,并获得整体更顺畅的体验。有可能 与WCF轻松集成。请记住,WCF仍将检查您的各种合同,以生成正确的WSDL和各种元数据。
还有其他因素可能会降低WCF启动速度,例如确定默认Web代理。确保这一点 useDefaultWebProxy
是 false
在您的绑定配置中,如果您没有任何用途。
不过,无论你采取什么措施来优化它,你都会发现WCF启动通常很慢。就个人而言,厌倦了类似场景中的缓慢战斗(我控制了两端,而客户端是一个WPF应用程序),我只是放弃了WCF并且去了 ServiceStack + protobuf-net。第一个呼叫从2-3秒到大约100毫秒,所有后续的HTTP呼叫都是瞬时的。整体用户体验大大提升。请注意,我与ServiceStack没有任何关系,这只是我的经验。
您是否通过查看生成的服务引用确认DataContractSerializer确实正在使用?由于添加服务引用操作期间的某些模式不匹配,可能会生成XmlSerializer代码而不是默认的DataContractSerializer,这会导致此行为是XmlSerializer的典型特征。在这种情况下,如您所述 - 您可以预先生成序列化代码以改善冷启动: http://msdn.microsoft.com/en-us/library/aa751883.aspx。
谢谢。
您可以通过预加载WCF服务来改善冷启动时间......即。不要等待第一个请求导致它被加载...提前加载。
只是一些想法......“可能”有助于加速序列化领域的事情。
关于为您的服务类型预生成序列化程序集.... Project | Build中有一个名为“Generate Serialization Assembly”的选项....如果切换为“On”,那么它会在Build time生成程序集而不是在运行时动态。
目前尚不清楚此选项是仅用于基于XMLSerializer的序列化程序的预生成序列化程序集,还是用于DataContractSerializers。您可以尝试将其切换为“开”以查看它是否有所作为。
您也可以尝试在客户端和服务器的代码中尽早执行此操作,以运行DataContract序列化程序...即。在客户端或服务器必须处理请求之前...(不确定它是否有帮助)。
DataContractSerializer ps = new DataContractSerializer(typeof(Person));
DataContractSerializer cs = new DataContractSerializer(typeof(Company));
etc...
为了使其更易于维护,您可以编写一个使用反射来定位您要序列化的类型的例程,例如寻找标有DataContract ....或其他一些启发式......或预定义表格的类型。