4

状況は次のとおりです。

Silverlight 3アプリケーションは、asp.netでホストされているWCFサービスにアクセスして、グリッドに表示するアイテムのリストを取得します。リストがクライアントに渡されると、IsolatedStorageにキャッシュされます。これは、DataContractSerializerを使用して、これらすべてのオブジェクトをストリームにシリアル化し、ストリームに圧縮してから暗号化することで実行されます。アプリケーションが再起動されると、最初にキャッシュからロードされ(上記のプロセスが逆になります)、DataContractSerializer.ReadObject()メソッドを使用してオブジェクトが逆シリアル化されます。これはすべて、最近まですべてのシナリオでうまく機能し、「キャッシュからのロード」パス全体(復号化/解凍/逆シリアル化)に最大で数百ミリ秒かかりました。

一部の開発マシンでは、すべてではありませんが(すべてのマシンWindows 7)、逆シリアル化プロセス-つまり、ReadObject(stream)の呼び出しには数分かかり、マシン全体がロックされているように見えますが、VS2008でデバッガーで実行している場合のみです。デバッガーの外部でデバッグ構成コードを実行しても問題はありません。

疑わしいと思われることの1つは、例外の停止をオンにすると、ReadObject()が多数のSystem.FormatExceptionをスローし、数値が正しい形式ではなかったことを示していることがわかります。「JustMyCode」をオフにすると、何千ものこれらが画面にダンプされます。処理されないものはありません。これらは、キャッシュからのリードバックと、WCFサービスからデータを取得するためのWebサービス呼び出しの終了時の逆シリアル化の両方で発生します。ただし、これらの同じ例外は、速度の低下をまったく経験していない私のラップトップ開発マシンで発生します。そしてFWIW、私のラップトップは本当に古く、私のデスクトップは4コア、6GBのRAM獣です。

繰り返しますが、VS2008のデバッガーで実行しない限り、問題はありません。他の誰かがこれに見えますか?何かご意見は?

バグレポートのリンクは次のとおりです:https ://connect.microsoft.com/VisualStudio/feedback/details/539609/very-slow-performance-deserializing-using-datacontractserializer-in-a-silverlight-application-only-in-debugger

編集:FormatExceptionsがどこから来ているのかがわかりました。それらは「設計による」ようです-double.NaNをシリアル化して、xmlがNaNのように見える場合に発生します... DCSが値を数値として解析しようとしているようですが、失敗します例外を除いて、「NaN」などを検索します。al。そしてそれらを処理します。私の問題は、これが機能しないということではありません...それは機能します...それはデバッガーを完全に機能不全にするだけです。これをより効率的に処理するようにdebugger/vs2008sp1を構成する方法を知っている人はいますか。

4

5 に答える 5

2

カートデン、

代わりに、XMLSerializerへの切り替えを検討することをお勧めします。これが私が時間をかけて決定したことです:

XMLSerializerクラスとDataContractSerializerクラスは、XMLとの間でオブジェクトグラフをシリアル化および逆シリアル化する簡単な手段を提供します。

主な違いは次のとおり
です。1。
[XmlElement]の代わりに[XmlAttribute]を使用すると、XMLSerializerのペイロードはDCSよりもはるかに小さくなります 。DCSは
常に値を要素として格納します。2。DCS は「オプトアウト」ではなく「オプトイン」 です。 [DataMember]でシリアル化するものを明示的にマークするDCSを使用する と、保護またはプライベートとしてマークされている場合でも、任意のフィールドまたはプロパティをシリアル化 できます。DCSを使用すると、[IgnoreDataMember]を使用してシリアライザーに特定のプロパティを無視させることができます。





XMLSerializerを使用すると、パブリックプロパティがシリアル化され、セッターを逆シリアル化する必要があり
ます。XmlSerializerを使用すると、[XmlIgnore]を使用して、シリアライザーにパブリックプロパティを無視させることができ ます

DCS.ReadObjectは、逆シリアル化中にコンストラクターを呼び出さない
初期化を実行する必要がある場合、DCSは次のコールバックフックをサポートします:
[OnDeserializing]、[OnDeserialized]、[OnSerializing]、[OnSerialized]
(バージョン管理の問題の処理にも役立ちます

) 2つのシリアライザーを切り替える機能では、次のように、両方の属性セットを同時に使用できます。

[DataContract]
[XmlRoot]
    public class ProfilePerson : NotifyPropertyChanges
    {
[XmlAttribute]
[DataMember]
        public string FirstName { get { return m_FirstName; } set { SetProperty(ref m_FirstName, value); } }
        private string m_FirstName;
[XmlElement]
[DataMember]
        public PersonLocation Location { get { return m_Location; } set { SetProperty(ref m_Location, value); } }
        private PersonLocation m_Location = new PersonLocation(); // Should change over time
[XmlIgnore]
[IgnoreDataMember]
        public Profile ParentProfile { get { return m_ParentProfile; } set { SetProperty(ref m_ParentProfile, value); } }
        private Profile m_ParentProfile = null;

        public ProfilePerson()
        {
        }
    }

また、2つを切り替えることができる私のSerializerクラスをチェックしてください:

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace ClassLibrary
{
    // Instantiate this class to serialize objects using either XmlSerializer or DataContractSerializer
    internal class Serializer
    {
        private readonly bool m_bDCS;

        internal Serializer(bool bDCS)
        {
            m_bDCS = bDCS;
        }

        internal TT Deserialize<TT>(string input)
        {
            MemoryStream stream = new MemoryStream(input.ToByteArray());
            if (m_bDCS)
            {
                DataContractSerializer dc = new DataContractSerializer(typeof(TT));
                return (TT)dc.ReadObject(stream);
            }
            else
            {
                XmlSerializer xs = new XmlSerializer(typeof(TT));
                return (TT)xs.Deserialize(stream);
            }
        }

        internal string Serialize<TT>(object obj)
        {
            MemoryStream stream = new MemoryStream();
            if (m_bDCS)
            {
                DataContractSerializer dc = new DataContractSerializer(typeof(TT));
                dc.WriteObject(stream, obj);
            }
            else
            {
                XmlSerializer xs = new XmlSerializer(typeof(TT));
                xs.Serialize(stream, obj);
            }

            // be aware that the Unicode Byte-Order Mark will be at the front of the string
            return stream.ToArray().ToUtfString();
        }

        internal string SerializeToString<TT>(object obj)
        {
            StringBuilder builder = new StringBuilder();
            XmlWriter xmlWriter = XmlWriter.Create(builder);
            if (m_bDCS)
            {
                DataContractSerializer dc = new DataContractSerializer(typeof(TT));
                dc.WriteObject(xmlWriter, obj);
            }
            else
            {
                XmlSerializer xs = new XmlSerializer(typeof(TT));
                xs.Serialize(xmlWriter, obj);
            }

            string xml = builder.ToString();
            xml = RegexHelper.ReplacePattern(xml, RegexHelper.WildcardToPattern("<?xml*>", WildcardSearch.Anywhere), string.Empty);
            xml = RegexHelper.ReplacePattern(xml, RegexHelper.WildcardToPattern(" xmlns:*\"*\"", WildcardSearch.Anywhere), string.Empty);
            xml = xml.Replace(Environment.NewLine + "  ", string.Empty);
            xml = xml.Replace(Environment.NewLine, string.Empty);
            return xml;
        }
    }
}
于 2010-03-08T05:48:57.103 に答える
1

これは推測ですが、すべての例外について、デバッグウィンドウなどに例外を表示するためにいくつかのアクションを実行しているため、デバッグモードでは低速で実行されていると思います。リリースモードで実行している場合、これらの追加の手順は実行されません。 。

私はこれを行ったことがないので、それが機能するかどうかは本当にわかりませんが、他のすべてのアセンブリがデバッグに設定されている間に、その1つのアセンブリをリリースモードで実行するように設定してみましたか?私が正しければ、それはあなたの問題を解決するかもしれません。私が間違っているなら、あなたはたった1、2分しか無駄にしません。

于 2010-03-16T15:42:22.437 に答える
1

デバッグの問題について、例外アシスタントを無効にしようとしましたか?([ツール]>[オプション]>[デバッグ]>[例外アシスタントを有効にする])。

もう1つのポイントは、[デバッグ]> [例外]での例外処理です。CLRのユーザーが処理しないものを無効にするか、System.FormatException例外のチェックを外すだけです。

于 2010-03-16T16:05:24.960 に答える
1

わかりました-根本的な問題を理解しました。それは私が主な質問への編集でほのめかしたものでした。問題は、xmlで、double.NaNの値を持つdoubleを正しくシリアル化していたことでした。これらの値を使用して、分母が0Dの場合の「na」を示していました。例:平均エクイティが0Dの場合のROE(株主資本利益率=純利益/平均エクイティ)は、次のようにシリアル化されます。

<ROE>NaN</ROE> 

DCSがそれを逆シリアル化しようとしたとき、明らかに最初に番号を読み取ろうとし、それが失敗したときに例外をキャッチしてからNaNを処理します。問題は、これがDEBUGモードのときに多くのオーバーヘッドを生成するように見えることです。

解決策:プロパティをdoubleに変更しましたか?NaNではなくnullに設定します。すべてがDEBUGモードで即座に実行されるようになりました。皆様のご協力に感謝いたします。

于 2010-03-17T05:13:11.730 に答える
0

一部のIEアドオンを無効にしてみてください。私の場合、LastPassツールバーがSilverlightのデバッグを強制終了しました。ブレークポイントの後でVisualStudioを操作するたびに、コンピューターが数分間フリーズしていました。

于 2011-11-03T14:29:08.883 に答える