Compact Framework のメモリ管理

W-Zero3 用のメモリ状況を表示するアプリケーションを作ってみたところ、メモリの挙動がおかしい。
 
たとえば、
起動初期状態で25MBほどあるフリーメモリーが、アプリを起動した後は22MBぐらいになる。
その後、メールを見たり、IEを開いたり、いろいろ使っているうちに10MBぐらいになる。
その後、すべてのアプリケーションを閉じてメモリを解放しても、初期の25MBには戻らず、15MB程度になる。
 
最初、プログラムのメモリ管理が悪く、Disposeまわりでメモリーリークが発生しているのかと思っていろいろやってみたが、先にポスとしたプログラムなので、そんなメモリリークが発生するような複雑なコードではない。
 
MSDN を調べてみたところ、やはりシステム側で動的にキャッシュを管理しているということですね。
 
MSDN の記事は次の通り。
 

RAM ストレージ

ランダム アクセス メモリ (RAM) を使用して、動的なデータ構造と JIT でコンパイルされたコードを保存します。.NET Compact Framework は、デバイスで指定された制限内で、使用可能な RAM を使用して生成されたコードやデータ構造をキャッシュし、後から適宜メモリを解放します。

メモリ不足になると、共通言語ランタイムではコードピッチ技法を使用して、JIT でコンパイルされたコード ブロックを実行時に解放します。これにより、RAM に制約のあるシステムで大きいプログラムを実行するときに、パフォーマンスの低下を最小限に抑えることができます。
 』

W-Zero3 用開発環境設定

レイアウトに関するメモ
 
メニュー→ターゲットプラットフォームの変更で、
『Windows Mobile 5.0 Pocket PC SDK』 を選択。
 
Form のプロパティで、FormFactor を
『Windows Mobile 5.0 Pocket PC VGA』を選択。
 
これをで正しくレイアウトができた。
 
—————–
ターゲットプラットフォームの変更で、Windows CE 5.0 だと、VS2005では 640×480 でレイアウトできるが、
実行すると、320×240 のサイズになってしまう。
 
 

緯度、経度より標高を返すクラス

緯度、経度より標高を返す web service を発見。
 
とりあえず、Windows Formsで作ってみた。
Compact Framework 5.0 で、ネームスペースサポートされているのかな・・・
 
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
using System.Diagnostics;
using System.Xml;
namespace Uchukamen.WZero3
{
    class Altitude
    {
        private const string webServiceUrl = "http://lab.uribou.net/ll2h/";
        public static float GetAltitude(string latitude, string longitude)
        {
            string encodedUrl = GetEncodedUrl(latitude, longitude);
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(encodedUrl);
            req.Method = "GET";
            float height = 0F;
            int err = 0;
            string msg = "";
            // レスポンスの取得と読み込み
            WebResponse res = req.GetResponse();
            using (Stream resStream = res.GetResponseStream())
            using (XmlTextReader reader = new XmlTextReader(resStream))
            {
                while (!reader.EOF)
                {
                    if (reader.IsStartElement("height"))
                        height = reader.ReadElementContentAsFloat();
                    else if (reader.IsStartElement("error"))
                        err = reader.ReadElementContentAsInt();
                    else if (reader.IsStartElement("message"))
                        msg = reader.ReadElementString("message");
                    else
                        reader.Read();
                }
                if (err != 0)
                    throw (new Exception(msg));
            }
            return height;
        }
        private static string GetEncodedUrl(string latitude, string longitude)
        {
            string url = webServiceUrl + "?ll="
                + latitude + "," + longitude;
            string encodedUrl = HttpUtility.HtmlEncode(url);
            return encodedUrl;
        }
    }
}
呼び出し
            textBoxAltitude.Text= Altitude.GetAltitude(textBoxLatitude.Text, textBoxLongitude.Text).ToString();

W-ZERO3用 CPU使用率取得クラス

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace Uchukamen.WZero3
{
    class CPUStatus
    {
        [DllImport("COREDLL.DLL")]
        private extern static uint GetTickCount();
        [DllImport("COREDLL.DLL")]
        private extern static uint GetIdleTime();
        private static uint dwStartTick = 0;
        private static uint dwIdleSt = 0;
        /// <summary>
        /// CPU使用率
        /// </summary>
        /// <returns>uint 0:最小-100:最大</returns>
        public uint GetCPU()
        {
            uint dwStopTick = GetTickCount();
            uint dwIdleEd = GetIdleTime();
            uint idle = ((100 * (dwIdleEd – dwIdleSt)) / (dwStopTick – dwStartTick));
            dwStartTick = dwStopTick;
            dwIdleSt = dwIdleEd;
            uint cpu = 100 – idle;
            Debug.WriteLine(cpu.ToString());
            return cpu;
        }
    }
}
 
呼び出し
            CPUStatus cpuStat = new CPUStatus();
            uint cpu = cpuStat.GetCPU();

W-ZERO3用 ディスク容量取得クラス

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Uchukamen.WZero3
{
    public class DiskStatus
    {
        [DllImport("coredll.dll")]
        public static extern bool GetDiskFreeSpaceEx
           (
           string directory,
           ref UInt64 lpFreeBytesAvailableToCaller,
           ref UInt64 lpTotalNumberOfBytes,
           ref UInt64 lpTotalNumberOfFreeBytes
           );
        #region プロパティ
        /// <summary>
        /// The total number of free bytes on the disk
        /// that are available to the user associated with the calling thread.
        /// </summary>
        private UInt64 freeBytesAvailableToCaller = 0;
        public UInt64 FreeBytesAvailableToCaller
        {
            get { return freeBytesAvailableToCaller; }
        }
        public float FreeMB
        {
            get { return (float)freeBytesAvailableToCaller / 1024F / 1024F; }
        }
       
        /// <summary>
        /// The total number of bytes on the disk
        /// that are available to the user associated with the calling thread.
        /// </summary>
        private UInt64 totalNumberOfBytes = 0;
        public UInt64 TotalNumberOfBytes
        {
            get { return totalNumberOfBytes; }
        }
        public float TotalMB
        {
            get { return (float)totalNumberOfBytes/1024F/1024F; }
        }
       
       
        /// <summary>
        /// The total number of free bytes on the disk.
        /// </summary>
        private UInt64 totalNumberOfFreeBytes = 0;
        public UInt64 TotalNumberOfFreeBytes
        {
            get { return totalNumberOfFreeBytes; }
        }
        #endregion
        /// <summary>
        /// ディスク容量を取得する。
        /// </summary>
        /// <param name="path">ディスクのパス</param>
        public void Get(string path)
        {
            bool res = GetDiskFreeSpaceEx(
                path,
                ref freeBytesAvailableToCaller,
                ref totalNumberOfBytes,
                ref totalNumberOfFreeBytes);
        }
    }
}
呼び出し
            DiskStatus dstat = new DiskStatus();
            dstat.Get("\\");

            textBox1.Text +=
             "空き容量     " + dstat.FreeMB.ToString("n2") + " MB\r\n" +
             "合計容量     " + dstat.TotalMB.ToString("n2") + " MB\r\n";

 

W-ZERO3用 メモリ容量取得クラス

W-ZERO3 プログラミングコンテスト用の部品を作り始める。
1月末まであと10日。実質、3日間。間に合うか?
複雑なことはできないので、とりあえず簡単にできるものを。
 
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
 
namespace Uchukamen.WZero3
{
    public class MemoryStatus
    {
        private class MEMORYSTATUS
        {
            public uint dwLength = 0;
            public uint dwMemoryLoad = 0;
            public uint dwTotalPhys = 0;
            public uint dwAvailPhys = 0;
            public uint dwTotalPageFile = 0;
            public uint dwAvailPageFile = 0;
            public uint dwTotalVirtual = 0;
            public uint dwAvailVirtual = 0;
        }
        [DllImport("CoreDll.dll")]
        private static extern void GlobalMemoryStatus
        (
        MEMORYSTATUS lpBuffer
        );
        [DllImport("CoreDll.dll")]
        public static extern int GetSystemMemoryDivision
        (
        ref uint lpdwStorePages,
        ref uint lpdwRamPages,
        ref uint lpdwPageSize
        );
        private float totalPhys = 0;
        public float TotalPhysicalMB
        {
            get { return totalPhys; }
        }
        private float availPhys = 0;
        public float AvailPhysicalMB
        {
            get { return availPhys; }
        }
        private float totalVirtual = 0;
        public float TotalVirtualMB
        {
            get { return totalVirtual; }
        }
        private float availVirtual = 0;
        public float AvailVirtualMB
        {
            get { return availVirtual; }
        }
        public void Get()
        {
            uint storePages = 0;
            uint ramPages = 0;
            uint pageSize = 0;
            int res = GetSystemMemoryDivision(ref storePages, ref ramPages, ref pageSize);
            MEMORYSTATUS memStatus = new MEMORYSTATUS();
            GlobalMemoryStatus(memStatus);
            totalPhys = memStatus.dwTotalPhys / 1024F / 1024F;
            availPhys = memStatus.dwAvailPhys / 1024F / 1024F;
            totalVirtual = memStatus.dwTotalVirtual / 1024F / 1024F;
            availVirtual = memStatus.dwAvailVirtual / 1024F / 1024F;
        }
    }
}
 
呼び出し
            MemoryStatus mstat = new MemoryStatus();
            mstat.Get();            textBox1.Text =
             "合計 物理   " + mstat.TotalPhysicalMB.ToString("n2") + " MB\r\n" +
             "空き 物理   " + mstat.AvailPhysicalMB.ToString("n2") + " MB\r\n" +
             "合計 仮想   " + mstat.TotalVirtualMB.ToString("n2") + " MB\r\n" +
             "空き 仮想   " + mstat.AvailVirtualMB.ToString("n2") + " MB\r\n";
 

Windows Mobile 開発メモ

開発環境構築メモ
 
1.VS2005 をインストール
2.Windows Mobile 5.0 SDK for Pocket PC (英語)をインストール 約174MB
   READMEによると、
  SDKを入れる前に、Please disable any virus checking software prior to installation. すること。
  ActiveSync over Ethernetは動かない。
  言語ごとにあるので、Windows Mobile 5.0 Emulator Images for Pocket PC – JPN.msi を選択。約106MB
  インストール時に、SDKとActiveSync 4.0 が必要と表示されるが、必要なし。
 
 
 

Google Maps API Version 2 Documentation

 
 結構遊べそう。