裏の最近のブログ記事
何かとお世話になるDispacher.BeginInvokeですが、DispacherプロパティはDependencyObjectのメンバーであるため、DependencyObjectを継承していないクラスなどでBeginInvokeを使いたくなった時に困ってしまうことがしょっちゅう...というほどではありませんが、極稀にあります。
「そもそも設計が間違っている」というご指摘には、「ごもっともです」と深くうなだれるより他にありませんが、絶対に無理かというとそうでもなく、それが正しい解法なのかどうかはともかくとして、とりあえず何とかなってしまったりします。
Deployment.Current.Dispacher.BeginInvoke
余りにもブログを更新していなかったので、昔の下書きにちょっと手を入れてそのまま公開してみました。
そのため、自分でも上記内容がほんとうに正しいのかどうか確信が持てない状況ですので、良い子は決して真似しないよう、くれぐれもよろしくお願いいたします。
残念ながらできません。
アプリケーション起動時にIsolatedStorage内のデータを読み込んで削除し、終了時に再度すべて保存し直すという方法も検討しましたが、コントロールパネルからアンインストールされた際には結局データが残ってしまいますし、アプリケーションが正常終了しなかった場合に全保存データが失われてしまうというリスクもあるため、今回は実装を見合わせました。
これは是非なんとかして欲しいんですが、Silverlight5ではどうなってるんでしょう?
Windows7で高DPI設定にした時だけ、OOB(Out-of-browser)アプリケーションウインドウ内のコンテンツが、ウインドウからはみ出してしまうという現象が発生してしまいました。
DPIの変更自体にはXPから対応しているのですが、どうしてWindows7でだけ問題が生じるのですか?ボクカナシイ
特別な設定でしか発生しない現象なら、別に対応しなくても良いよね!なんて思っていたのですが、聞いたところによると、標準で125%(120DPI)に設定されているPCもあるとかで、仕方なく調査に乗り出したのでした。(第一部・完)
最初は、ものすごく面倒な対応を強いられるのではないかと思っていたのですが(全コントロールのサイズをDPI比から算出して再設定するとか)、調査をはじめて三日目の晩、実家の茶の間に飾られた白黒写真でしか見たことのない曽祖父が夢枕に立ち、「SettingsクラスのEnableAutoZoom プロパティ」と呟いたところではっと目が覚めた僕は、早速以下の一行をAppクラスのコンストラクタに追記してみました。
Host.Settings.EnableAutoZoom = false;
上記の一行加えただけで、見た目は標準のDPI(96DPI)設定時と同じように表示されるようになり、動作上も今のところは特に問題なさそうです。
本当はちゃんと解像度設定に従うような実装を心がけるべきなんでしょうが、今さらもうどうしようもない!なんて時はとりあえずこんな感じで対応するのもやむなしってことで、僕は引き続き「マルマルモリモリ」の振り付けを覚える仕事に戻りたいと思います。
ホントは環境による処理の振り分けなんてしたくはないんですが、Silverlight側のバグへの対応という話になると、そう悠長なことも言っていられません。
兄ちゃん、なんでMacの時だけWebBrowserコントロール消えてしまうん?
ということで、Macの時だけ力技で対応することにしたのですが、Macかどうかの判定は以下のように行なっています。
if (Environment.OSVersion.Platform == PlatformID.MacOSX)
{
// Macだけの処理
}
本当にちなみにですが、MacでWebBrowserが消えてしまう(再描画されない)不具合への対応方法は、こちらのページを参考にしました。
GIF画像の表示くらい普通に対応してくれればいいのにー!
なんて文句を言っていても仕方が無いので、MS謹製ライブラリ「ImageTools」を使ってGIF画像を表示することにしたのですが、つまらないことで少しだけはまってしまったのでメモ。
ImageToolsの入手は以下の公式サイトから。ライセンスはMs-PLです。
http://imagetools.codeplex.com/
/*
// 初期化の際に一度だけ必要な処理
▼AddReferencesが必要なDLL
ImageTools.dll // 当然必要なライブラリ本体
ImageTools.IO.Gif.dll // これを忘れる人はいないでしょう
ImageTools.IO.Png.dll // これが必要だと気づかずにはまった
ImageTools.Utils.dll // ToBitmapするのに必要
*/
ImageTools.IO.Decoders.AddDecoder<GifDecoder>();
ExtendedImage eximg = new ExtendedImage();
// GIF画像読み込み完了時の処理
eximg.LoadingCompleted += (sender, args) =>
{
Dispatcher.BeginInvoke(() =>
{
// image = XAML側に配置してあるImage
image.Source = eximg.ToBitmap();
});
};
// GIF画像読み込み開始
eximg.UriSource = new Uri("http://hoge.com/foo.gif", UriKind.Absolute);
サーバからのデータ取得を行うたびに、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();
呼び出しはたったのこれだけ。
パフォーマンスが著しく低下するから、呼び出さない方が良いよ、なんて言われても、どうしても呼び出したい時というのはあるものです。
でも、くれぐれも使いどころにはお気を付けください。


