11

几天来,我一直在为我们的 WPF 应用程序问题而苦苦挣扎,我想知道是否有人以前遇到过这个问题并且可以提供帮助?问题似乎归结为客户端生成“即时”序列化程序来处理该 Web 方法调用中的类型。当第一次调用该方法时(Web 服务本身已经在运行),它可能需要例如 8 秒,后续调用可能需要例如 20 毫秒。在此延迟期间,客户端 WPF 进程上的 CPU 非常高。

使用 XmlSerializer 时,有一种方法可以使用 svcutil 预先生成这些序列化程序程序集。当(就像我们一样)使用普通的 WCF DataContractSerializer 时,这个选项似乎不存在。

我想要的是能够为我的所有数据合约(很多)中的所有类型预先生成这个程序集,或者,用我可以编码并以二进制形式传递数据的自定义程序替换这个过程(我们拥有此 Web 服务/客户端的两端,它们都是 .NET 4)。我已经使用了 BinaryForamtter 和 GZip 压缩,虽然这加快了数据的传输,但它总是被恢复为 XML 以由框架反序列化,因此这个问题仍然存在。

有任何想法吗?

4

3 回答 3

8

您可以使用诸如protobuf-net之类的二进制库,它非常快,即使由于必须为每种类型生成代码而存在初始启动成本,但它仍然DataContractSerializerorBinaryFormatter好得多。您应该获得几秒钟的时间并获得整体更流畅的体验。它可以很容易地与 WCF 集成。请记住,WCF 仍将检查您的各种合同以生成正确的 WSDL 和各种元数据。

还有其他可能会减慢 WCF 启动速度的因素,例如确定默认 Web 代理。如果您对它没有任何用处,请确保它useDefaultWebProxy在您的绑定配置中。false

尽管如此,您会发现无论您如何优化 WCF 启动通常都很慢。就个人而言,厌倦了在类似的场景中与缓慢作斗争(我控制了两端,并且客户端是 WPF 应用程序),我干脆放弃了 WCF 并选择了ServiceStack + protobuf-net。第一次调用从 2-3 秒缩短到 100 毫秒左右,所有后续的 HTTP 调用都是即时的。整体的用户体验有了很大的提升。请注意,我绝不隶属于 ServiceStack,这只是我的经验。

于 2012-10-11T09:27:11.447 回答
2

您是否通过查看生成的服务引用确认 DataContractSerializer 确实在使用?可能由于在添加服务引用操作期间存在一些架构不匹配,生成了 XmlSerializer 代码而不是默认的 DataContractSerializer,这导致了 XmlSerializer 的这种典型行为。在这种情况下,正如您所指出的 - 您可以预先生成序列化代码以改进冷启动: //msdn.microsoft.com/en-us/library/aa751883.aspx。谢谢。

于 2012-10-12T18:06:41.247 回答
0

您可以通过预加载 WCF 服务来改善冷启动时间...即不要等待第一个请求导致它被加载...提前加载。

只是一些想法......“可能”有助于加快序列化领域的速度。

关于为您的服务类型预生成序列化程序集....项目|构建中有一个名为“生成序列化程序集”的选项....如果切换为“打开”,那么它会在构建时生成程序集,而不是在运行时动态。

目前尚不清楚此选项是否仅适用于基于 XMLSerializer 的序列化程序或 DataContractSerializers 的序列化程序集的预生成。您可以尝试将其切换为“开”,看看它是否有所作为。

您也可以尝试在客户端和服务器的代码中尽早执行此操作,以练习 DataContract 序列化程序......即在客户端或服务器必须处理请求之前......(不确定它是否有帮助)。

DataContractSerializer ps = new DataContractSerializer(typeof(Person));
DataContractSerializer cs = new DataContractSerializer(typeof(Company));
etc...

为了使其更易于维护,您可以编写一个例程,使用反射来定位您打算序列化的类型,例如查找标有 DataContract ....或其他一些启发式方法...或预定义表的类型。

于 2012-10-11T10:00:42.230 回答