質問

Microsoft Dynamics CRMでいくつかの実験を行っています。あなたはウェブサービスを通してそれと対話し、私のプロジェクトにウェブ参照を追加しました。ウェブサービスインターフェースは非常に豊富で、生成された「Reference.cs」は約90k locです。

コンソールアプリケーションでWeb参照を使用しています。私はしばしば何かを変更し、再コンパイルして実行します。コンパイルは高速ですが、Webサービス参照の更新は非常に遅く、15〜20秒かかります。 <コード>     CrmService service = new CrmService(); プロファイリングにより、すべての時間がSoapHttpClientProtocolコンストラクターで費やされていることがわかります。

犯人は、明らかに、XMLシリアル化コード(上記の90k locには含まれていません)が、JITされる前に実行時に生成されるという事実です。これは、コンストラクターの呼び出し中に発生します。いろいろと遊んだり試したりするときの待ち時間はかなりイライラします。

sgen.exe、ngen、XGenPlus(数時間かかり、500MBの追加コードを生成する)のさまざまな組み合わせを試しましたが、役に立ちませんでした。必要に応じて準備を整えるCrmServiceインスタンスがほとんどないWindowsサービスの実装を検討しましたが、それは過剰に思えます。

アイデアはありますか

役に立ちましたか?

解決

以下は、VMWareフォーラムの this スレッドから引用されています。

こんにちは、

sgen.exeが機能することがわかりました。このスレッドでは見落としていたシリアライザーdllの事前生成以外に、いくつかの追加のステップがあるだけです。詳細な手順は次のとおりです

問題

.NETからVIM 2.0 SDKを使用する場合、VimServiceクラスをインスタンス化するのに長い時間が必要です。 (VimServiceクラスは、「wsdl.exe vim.wsdl vimService.wsdl」を実行して生成されるプロキシクラスです)

つまり、次のコード行:

_service = new VimService();

実行に約50秒かかります。

原因

明らかに、.NET XmlSerializer は、実行時にシリアル化コードを生成するためにプロキシクラスに注釈を付ける System.Xml.Serialization。* 属性を使用します。 VimService.csのコードのように、プロキシクラスが多くて大きい場合、シリアル化コードの生成に時間がかかることがあります。

ソリューション

これは、Microsoft .NETシリアライザーの動作に関する既知の問題です。

MSDNがこの問題を解決するために提供しているリファレンスを次に示します。

http://msdn2.microsoft.com/en-us/library/ bk3w6240.aspx http://msdn2.microsoft.com/en-us /library/system.xml.serialization.xmlserializerassemblyattribute.aspx

残念ながら、上記の参考文献のいずれも、問題の完全な解決策を説明していません。代わりに、XMLシリアル化コードを事前生成する方法に焦点を当てています。

完全な修正には、次の手順が含まれます。

  1. 事前生成されたXMLシリアライザーコードを使用してアセンブリ(DLL)を作成します

  2. System.Xml.Serialization。*属性へのすべての参照をプロキシコードから削除します(つまり、VimService.csファイルから)

  3. XmlSerializerAssemblyAttributeでメインプロキシクラスに注釈を付けて、XMLシリアライザーアセンブリがある場所を指すようにします。

ステップ2をスキップしても、 VimService クラスのインスタンス化時間は20%しか改善されません。ステップ1または3のいずれかをスキップすると、誤ったコードになります。 3つのステップすべてで98%の改善が達成されています。

詳細な手順は次のとおりです。

始める前に、.NET verison 2.0ツールを使用していることを確認してください。 sgenツールと XmlSerializationAssemblyAttribute は.NETのバージョン2.0でのみ使用可能なため、このソリューションは.NETのバージョン1.1では機能しません

  1. wsdl.exeを使用して、WSDLからVimService.csファイルを生成します。

    wsdl.exe vim.wsdl vimService.wsdl

    これにより、現在のディレクトリにVimService.csファイルが出力されます

  2. VimService.csをライブラリにコンパイル

    csc / t:library /out:VimService.dll VimService.cs

  3. sgenツールを使用して、XMLシリアライザーを事前生成およびコンパイルします。

    sgen / p VimService.dll

    これにより、現在のディレクトリにVimService.XmlSerializers.dllが出力されます

  4. VimService.csファイルに戻り、すべての System.Xml.Serialization。* 属性を削除します。コードコードは大きいため、これを実現する最良の方法は、正規表現置換ツールを使用することです。すべての属性が単独で行に表示されるわけではないため、これを行う際には注意してください。いくつかはメソッド宣言の一部としてインライン化されています。

    この手順が難しい場合は、簡単な方法を以下に示します。

    C#を記述していると仮定して、次の文字列でグローバル置換を実行します。

    [System.Xml.Serialization.XmlIncludeAttribute

    それを次のものに置き換えます:

    // [System.Xml.Seri

他のヒント

をご覧ください。 .NETに付属のSgen.exe ツール。 Visual StudioのC#プロジェクトプロパティ&quot; Build&quot;には、便利な小さなものもあります。ページの一番下にある「シリアル化アセンブリのビルド」ページ。 Sgen が自動的に実行されます。

これはSGENの問題ではないと考えています。コンストラクターのコードを見て、多くのリフレクションを行っていることがわかりました(クラスのXmlIncludeAttributeに基づいて)。それらすべてに反映され、非常に長い時間がかかる場合があります。

CRMに付属する事前生成されたXmlSerializerアセンブリがあります。 GACにSdkTypeProxy.XmlSerializers.dllおよびSdkProxy.XmlSerializers.dllがあるかどうかを確認します。

そうしないと、CrmServiceの作成時に.netがXmlSerializerアセンブリを生成するため、時間がかかる場合があります。 これがお役に立てば幸いです

最初の SoapHttpClientProtocol の呼び出しに時間がかかった理由を見つけようとしたときに、このスレッドに出会いました。

プロキシをnull / Emptyに設定すると、プロキシの自動検出が停止することがわかりました-これは最初の呼び出しで最大7秒かかっていました:

this.Proxy = GlobalProxySelection.GetEmptyWebProxy();

上記の詳細な回答をガイドとして使用し、プロセスを自動化するスクリプトを作成して、いくつかのステップを進めました。スクリプトは2つのファイルで構成されています:

generateproxy.bat:

REM if your path for wsdl, csc or sgen is missing, please add it here (it varies from machine to machine)
set PATH=%PATH%;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools;C:\Program Files (x86)\MSBuild\14.0\Bin

wsdl http://localhost:57237/VIM_WS.asmx?wsdl REM create source code out of WSDL
PowerShell.exe -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'" REM proces source code (remove annotations, add other annotation, put class into namespace)
csc /t:library /out:references\VIM_Service.dll VIM_WS.cs REM compile source into dll
sgen /p references\VIM_Service.dll /force REM generate serializtion dll

generateproxy.ps1

(Get-Content VIM.cs) | 
    ForEach-Object { 
        

上記の詳細な回答をガイドとして使用し、プロセスを自動化するスクリプトを作成して、いくつかのステップを進めました。スクリプトは2つのファイルで構成されています:

generateproxy.bat:

REM if your path for wsdl, csc or sgen is missing, please add it here (it varies from machine to machine)
set PATH=%PATH%;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools;C:\Program Files (x86)\MSBuild\14.0\Bin

wsdl http://localhost:57237/VIM_WS.asmx?wsdl REM create source code out of WSDL
PowerShell.exe -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'" REM proces source code (remove annotations, add other annotation, put class into namespace)
csc /t:library /out:references\VIM_Service.dll VIM_WS.cs REM compile source into dll
sgen /p references\VIM_Service.dll /force REM generate serializtion dll

generateproxy.ps1

cd..\..
generateproxy

これら2つのファイルをクライアントプロジェクトに追加し、ビルド前イベントで行を追加しました

<*>

したがって、すべてのビルドの前に、プロキシクラスが再生成され、開発者は(ほとんど)考える必要がありません。ビルド中は、WSが稼働している必要があり、そのURLはbatファイルに含まれている必要があります。事前ビルドの結果、2つのdllファイルがクライアントプロジェクトのサブフォルダー references で再生成されます。 スクリプトの最初の実行後、新しいdllへの参照を追加する必要があります。

-replace "(?<attr>\[global::System.Xml.Serialization.[^\]]*\])", "/*${attr}*/" ` -replace "public partial class VIM", "[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = ""VIM_Service.XmlSerializers"")] `npublic partial class VIM" ` -replace "using System;", "namespace Classes.WS_VIM { `n`nusing System;" } | Set-Content VIM.cs Add-Content VIM.cs "`n}"

これら2つのファイルをクライアントプロジェクトに追加し、ビルド前イベントで行を追加しました

<*>

したがって、すべてのビルドの前に、プロキシクラスが再生成され、開発者は(ほとんど)考える必要がありません。ビルド中は、WSが稼働している必要があり、そのURLはbatファイルに含まれている必要があります。事前ビルドの結果、2つのdllファイルがクライアントプロジェクトのサブフォルダー references で再生成されます。 スクリプトの最初の実行後、新しいdllへの参照を追加する必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top