裏の最近のブログ記事
サーバからのデータ取得を行うたびに、IEのメモリ使用量が増えて行くという現象が発生してしまっていたので、SilverlightのメモリリークについてGoogle先生と一緒にいろいろ調べてみました。
以下はその時に試してみた方法のメモですが、内容については無保証ですので(このブログのエントリー全てそうですがw)、試される方は自己責任でお願い致します。
■Silverlight application memory leaks detector
リークが発生しているかを確認したいクラスのコンストラクタで
MemoryProfiler.AddReference(this);を呼び出せば、MemoryProfiler.checkを呼び出すことによって、使用メモリと、メモリ上に残っているAddRefferenceしたオブジェクトのインスタンス数を確認することができます。
■Silverlight Spy
Silverlightアプリケーションのメモリ使用量を含む、さまざまなデータを参照することができます。99ユーロ(個人使用なら69ユーロ)はちょっと高いけど、会社で買ってくれるっていうなら有ってもいいかも。
■Finding Memory Leaks In Silverlight With WinDbg
Microsoftが提供しているデバッグツール"WinDbg"(32bit版/64bit版)を使用した、Silverlightのメモリリーク検出方法。
手順を簡単にメモ。
- IE上でSilverlightアプリケーションを起動
- WinDbgを起動する(スタート→プログラム→Debugging Tools for Windows)
- WinDbgのメニューから[File]→[Attach to a Process]を選択し、プロセス一覧から"iexplore.exe"を選択してOKをクリック
- 画面下部のコマンド入力欄に以下のコマンドを入力してsos.dllをロード
.load C:\\Program Files\\Microsoft Silverlight\\3.0.40818.0\\sos.dll
(※ パスは環境によって変わります/※2 先頭の"."を忘れずに) - 以下のコマンドで、Silverlightアプリケーション内のインスタンス名、数、使用メモリが一覧表示されます。("SilverlightApplicationName"の部分は適宜編集してください)
!dumpheap -stat -type SilverlightApplicationName
さらに詳しい情報はこことかこことか。
【 結 論 】
メモリリークはなくてもブラウザのメモリ使用量は時間とともに増加する...らしい?
DateTimeクラスのTicksプロパティは、0001年1月1日00:00:00からの経過時間を100ナノ秒単位で返してくれる便利な奴ですが、ミリ秒程度ならともかく、マイクロ秒を飛ばしていきなり「ナノ秒」なんて言われても、ぱっと計算できるものではありません。
ということで、100ナノ秒単位で返って来る値を秒単位に変換する計算式(というほどでもないけどw)をメモ。
int seconds = DateTime.Now.Ticks / 10000000;
やっとSilverlight3に触っています。
最近すっかりJQueryにはまっている会長です。
かつてのブラウザ&OS依存により、JavaScript1.2だかなんだかあたりの某案件以来、極度のJavaScript嫌いに陥っていた僕ですが、必要に迫られて使うことになったJQueryのおかげで、今ではすっかりJavaScriptが楽しくて仕方がありません。
とりあえず、このブログにも、JQueryだけでも入れちゃっておこうかな。
というどうでもいい話はさておき、Silverlightコンテンツから、POST送信によるページ遷移を行う必要に迫られ、いろいろ調べてみたのですが、POSTリクエストを送信する方法はたくさん見つかったのですが、ページ遷移となるとなかなか情報が見つからなくて、途方に暮れていました。
そんな中、ふと思いついて試してみた方法が、予想以上にうまくいってしまいました。
もしかしたら、他にちゃんとした方法があるのかもしれませんが、同じ疑問を持っている方の参考になればと思い、以下にその方法を記録しておこうと思います。
もし間違っていたりしたら、親切な誰かが、正しい方法を教えてくれるしね(^^;
すでにSilverlight3もリリースされており、とっても気にはなっているのですが、実はまだまったく触っていません。
だってSilverlight2と3の開発環境が、共存させられないって言うんですもの...(ノ∀`)
一応、ちょっとしたハックで双方を同時に開発できる環境を構築することも可能なようですが、ちょっと怖いのでまだ試していません。
さて、通常は、SilverlightアプリケーションをホストするHTMLファイルと、SIlverlightアプリケーション本体であるXapファイルは、同じサーバに配置することが多いと思います。
リファレンスにも、「セキュリティ上の理由から、Silverlight プラグイン インスタンスがホストされている HTML ページとは異なるサイトの URI を Source プロパティとして設定することはできません。」という記述がありますし、実際に異なるドメインのサーバにファイルを配置してみても、多くの環境では、Silverlightアプリケーションが起動しないのではないかと思います。
それでは本当にHTMLとXapを別々のサーバに配置して、Silverlightアプリケーションを起動させることができないのかというとそうではなく、実はそれが可能な方法がちゃんとあります。
ポイントは、Xapファイルにアクセスした際にサーバが返す"Content-type"ヘッダです。
Xapファイルが配置されている側のサーバに、XapファイルのMIME Typeとして"application/x-silverlight-app"を登録してやることにより、HTMLとXapが別々のサーバに配置されていても、正常にSilverlightアプリケーションを起動させることができます。
但しこれは、試してみたら出来たというだけの話で、環境などの要因によって結果が異なる場合もあるかもしれませんし、また、HTML側のJavaScriptとSilverlightの連携などの機能が、一部正常に動作しない場合もあるようなので、どうしてもという場合以外は、同じサーバ上にファイルを配置しておいた方が安心だと思います。
Flex等では、"System.gc()"を呼び出すことによって、強制的にガベージコレクションを実行することができますが、Silverlightにはそういうのないのかな、と思っていたら、ちゃんと存在していたんですね。
GC.Collect();
呼び出しはたったのこれだけ。
パフォーマンスが著しく低下するから、呼び出さない方が良いよ、なんて言われても、どうしても呼び出したい時というのはあるものです。
でも、くれぐれも使いどころにはお気を付けください。
もう書いたと思っていたのにエントリーが見当たらなかったので改めてメモ。
方法自体はとっても簡単なのでとりあえずソースだけ。
StreamResourceInfo sri =
App.GetResourceStream(new Uri("/assemblyName;component/filename.jpg", UriKind.Relative));
BitmapImage bi = new BitmapImage();
bi.SetSource(sri.Stream);
Image img = new Image(){ Source = bi };
見難くてごめんなさい。
とあるアプリケーションが、MacのSafariで正常に動作しないという報告がクライアントからありました。
多少条件判定処理が多いくらいで、それ以外はどう考えてもごくごく普通の処理をしているだけの個所なのに、確かに動作がおかしかったので、前回のエントリーで書いたSilverlightとJavaScriptの連携を使ってログを吐きつつ調査をしてみたところ、恐ろしいことに気づいてしまいました。
double型って==演算子で比較しちゃダメなの?(´・ω・`)
明らかに等しいdouble値の==演算子の比較が常にfalseになっているようだったので、試しにEqualsで比較するようにしてみたら、正常に動作するようになりました。
確かにEqualsメソッドもあるけど、別に==で比較しても良いんじゃないの?ヽ(`Д´)ノ
何も明らかに等しい値を、しかもMacのSafariだけでスルーしなくても良いと思う(´;ω;`)
ということで、今後はdouble型の比較には、==演算子じゃなくてEqualsメソッドを使いましょう、というお話しでした。
でも忘れちゃいそうだなー( ;^ω^)
SilverlightアプリケーションからアプリケーションをホストしているHTMLファイルに記述されたJavaScriptのファンクションを呼び出す方法はこんな感じ。
ScriptObject jsFunction =
(ScriptObject)HtmlPage.Window.GetProperty("jsFunctionName");
if(jsFunction != null)
{
jsFunction .InvokeSelf(parameter);
}
引数を問題なく渡せることは確認しましたが、どんな型が渡せるのかとか、返り値もちゃんと渡って来るのかとか、外部JSファイルのファンクションはどうなんだ、とかいうのはまだ試していません。
JavaScriptからSilverlightアプリケーション内のメソッドを呼び出すこともできるのですが、それはまた次回。
これまで、XMLファイルをWebClientで読み込む処理は結構あったのですが、XAP内に同梱されたXMLを読み込んだことはなかったので、最初はどうすればいいかちょっと悩んでしまいました。
でも方法さえわかってしまえばとっても簡単。
プロジェクトにXMLファイルを追加して、"Build Action"を"Content"に設定してしまえば、あとは以下のような感じで読み込むことができます。
//data.xmlがSilverlightプロジェクト直下に配置されている場合
XmlReader reader = XmlReader.Create("data.xml");
僕の場合は、この後XDocument.Load(reader)して、LINQ to XMLでモニャモニャすることが多いです。
何かと便利なSilverlight.jsのリファレンスと、最新版の入手先と、さらに、いつか必要になりそうなSilverlight.supportedUserAgent.jsなんてものも発見したので併せてメモ。
■Silverlight.js
・最新版ダウンロード
http://code.msdn.microsoft.com/silverlightjs
・日本語版リファレンス
http://msdn.microsoft.com/ja-jp/library/cc838126(VS.95).aspx
■Silverlight.supportedUserAgent.js
・最新版ダウンロード
http://code.msdn.microsoft.com/SLsupportedUA


