概要: ベスト プラクティスは、使用する Web サービス クライアントをインスタンス化してから、範囲外にしてガベージ コレクションを取得することだと思います。これは、Microsoft から提供されたサンプルに反映されています。正当化は次のとおりです...
完全: 私が見つけたプロセスの最も完全な説明は、How to: Access a Service from Silverlight にあります。ここでの例は、Web サービス クライアントをインスタンス化し、(クライアントを閉じる必要なく) 範囲外にできるようにする典型的なパターンを示しています。Web サービス クライアントは、オブジェクトがガベージ コレクションされるときに、必要に応じて管理されていないリソースを解放する Finalize メソッドを持つ ClientBase から継承します。
私は Web サービスを使用したかなりの経験があり、プロキシを使用し、使用する直前にインスタンス化してから、ガベージ コレクションを許可します。このアプローチで問題が発生したことはありません。Wenlong Dong のブログで、プロキシの作成にはコストがかかると書かれていましたが、.NET 3.5 ではパフォーマンスが向上したとのことです (それ以降、再び向上したのでしょうか?)。私が言えることは、パフォーマンスは相対的な用語であり、取得するデータのサイズが小さい場合を除き、接続を作成するよりもシリアル化/逆シリアル化と転送にはるかに多くの時間が費やされるということです. これは確かに私の経験であり、最初にこれらの領域で最適化する方がよいでしょう.
最後に、これまでの私の意見では不十分かもしれないので、簡単なテストを書きました。Visual Web Developer 2010 Express で提供されているテンプレートを使用して、Silverlight 対応の Web サービスを作成しました (既定の void メソッドは と呼ばれますDoWork()
)。次に、サンプルの Silverlight クライアントで、次のコードを使用して呼び出しました。
int counter=0;
public void Test()
{
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
client.DoWorkCompleted += (obj, args) =>
{
counter++;
if (counter > 9999)
{
for(int j=0;j<10;j++) GC.Collect();
System.Windows.MessageBox.Show("Completed");
}
};
client.DoWorkAsync();
}
次に、Test メソッドを呼び出してfor(int i=0;i<10000;i++) Test();
、アプリケーションを起動しました。アプリの読み込みと Web サービスの呼び出し (10,000 回すべて) を完了するのに 20 秒強かかりました。Web サービスの呼び出しが行われている間、プロセスのメモリ使用量が 150MB を超えていましたが、呼び出しが完了してGC.Collect()
呼び出されると、メモリ使用量はその半分以下に減少しました。完璧なテストとはほど遠く、メモリ リークがないこと、または無視できるレベルであることを確認できたようです (すべて別のクライアント インスタンスを使用して 10,000 回の Web サービス呼び出しを呼び出すことはおそらく一般的ではないと考えてください)。また、プロキシ オブジェクトを保持し、障害が発生して再度開く必要があることを心配するよりも、はるかに単純なモデルです。
テスト方法論の正当化:
私のテストでは、2 つの潜在的な問題に焦点を当てました。1 つはメモリ リークで、もう 1 つはオブジェクトの作成と破棄に費やされたプロセッサ時間です。クラスを提供する会社 (Microsoft) が提供する例に従うことをお勧めします。ネットワークの効率が気になる場合は、これらのオブジェクトを適切に作成/破棄してもネットワークの遅延に影響しないため、この例で問題はないはずです。費やされた時間の 99% がネットワーク時間である場合、1% の理論上の改善のために最適化することは、おそらく開発時間の点で無駄です (得られる利点さえあると仮定すると、私のテストではほとんどないことが明らかに示されていると信じています/なし)。はい、ネットワーク呼び出しはローカルでした。つまり、10,000 回のサービス呼び出しの過程で、オブジェクトの待機に費やされるのは約 20 秒だけです。これは、オブジェクトの作成に費やされたサービス呼び出しごとに約 2 ミリ秒を表します。Dispose を呼び出す必要性については、必要がないように見えるだけで、それを呼び出すべきではありません。忘れた場合 (または単に忘れた場合)、私のテストでは、これらのオブジェクトの Finalize で Dispose が呼び出されていると信じていました。それでも、Dispose を自分で呼び出す方がおそらく効率的ですが、それでも効果は無視できます。ほとんどのソフトウェア開発では、(重大なメモリ リークがない限り) このような問題を突き止めるよりも、より効率的なアルゴリズムとデータ構造を考え出すことで、より多くの利益が得られます。XML に基づくシステムよりも効率的なデータ転送オプションがあるため、より効率が必要な場合は、おそらく Web サービスを使用しない方がよいでしょう。