ArcObjectsでマルチスレッド描画 2



ArcObjectsでマルチスレッド描画

水平分割はやったが、今度は垂直分割。
とりあえず行儀悪くSTAとかは考えないで.NET 4.0で確認してみた。

データフレームを分割し、上位に表示したいレイヤと下位に分離して読み込むと、データフレーム単位でスレッド分離される。
※スレッドプール次第だが

全体的に結果は良いが..課題は多そう。
少し数値がばらついているがレイヤの分け方なのかスレッド上げて待機した方が良いのか。。

現実的に使うには
Bitmap領域が水平分割と違って広くなっているので広い領域への対応が必要?
安定性と描画されないパターンの制御?

ここまでするならArcGIS Runtime SDK for WPFで非同期系に移行すべきだろうと言う線引きにはなるか
恐らくは下記挙動
・ミニローカルサーバなので恐らく多重命令可能?
・マップパッケージ分割で、対応スレッドが分かれる?

レイヤ 総計[ミリ秒]
マルチ 21994.24
シングル 29539.35
74.5%

極端に速い観測結果(恐らく何か異常)を除くと 80~90%程度の速度だろうからあまりふるわない結果かと

個別の速度

Layer Total [ミリ秒] 速度比
マルチ 381.89 107%
シングル 356.57 na
マルチ 435.02 90%
シングル 485.43 na
マルチ 1159.67 79%
シングル 1470.35 na
マルチ 2151.3 97%
シングル 2207.97 na
マルチ 1685.68 67%
シングル 2515.37 na
マルチ 3292.83 80%
シングル 4100 na
マルチ 2116.52 85%
シングル 2481.89 na
マルチ 1731.93 88%
シングル 1975.3 na
マルチ 1015.91 24%
シングル 4149.66 na
マルチ 1001.26 46%
シングル 2179.33 na
マルチ 2008.83 141%
シングル 1422.19 na
マルチ 903.92 70%
シングル 1294.1 na
マルチ 1407.66 84%
シングル 1668.38 na
マルチ 1271.53 91%
シングル 1397.67 na
マルチ 1430.29 78%
シングル 1835.14 na

コードは下記

using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

[ComVisible(true)]
[Guid("D5FBE404-FF4C-4976-9E51-02684C2FB11E")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("Custom.CustomMXDThreadLayerV")]
public class CustomMXDThreadLayerV : CustomMxdLayer
{
  [Persist()]
  public string m_MapsMxd = null;

  private List<IMap> m_Maps = new List<IMap>();

  public CustomMXDThreadLayerV()
    : base()
  {
  }
  public CustomMXDThreadLayerV(string mxd)
    : base(mxd)
  {
    this.m_MapsMxd = mxd;
  }

  protected override void InitMap()
  {
    if (!string.IsNullOrEmpty(this.m_MapsMxd))
      base.m_MapDocPath = this.m_MapsMxd;
    else if (!string.IsNullOrEmpty(base.m_MapDocPath))
      this.m_MapsMxd = base.m_MapDocPath;

//    base.InitMap();

    using (ComReleaser com = new ComReleaser())
    {
      IMapDocument mapDoc = new MapDocumentClass();
      com.ManageLifetime(mapDoc);

      mapDoc.Open(this.m_MapsMxd, null);

      for (int i = 0; i < mapDoc.MapCount; i++)
      {

        IMap map = mapDoc.get_Map(i);
        this.m_Maps.Add(map);

        if (i == 0)
        {
          base.m_Map = map;
        }
      }//end loop

      mapDoc.Close();
    }//end com
  }//end method

  public override void Draw(esriDrawPhase DrawPhase, IDisplay Display, ITrackCancel TrackCancel)
  {
    IDisplayTransformation diTransform = Display.DisplayTransformation;

    tagRECT rect = diTransform.get_DeviceFrame();
    int scWidth = rect.right;
    int scHeight = rect.bottom;

    List<Task<Bitmap>> drawTask = new List<Task<Bitmap>>(this.m_Maps.Count);
    for (int i = 0; i < this.m_Maps.Count; i++)
    {
      var t = Task.Factory.StartNew(obj =>
      {
        int index = Convert.ToInt32(obj);
        using (ComReleaser com = new ComReleaser())
        {
          IMap map = this.m_Maps[index];

          IPoint leftU = diTransform.ToMapPoint(0, 0);
          com.ManageLifetime(leftU);

          IPoint rightB = diTransform.ToMapPoint(scWidth, scHeight);
          com.ManageLifetime(rightB);

          IEnvelope env = new EnvelopeClass();
          com.ManageLifetime(env);
          env.PutCoords(leftU.X, leftU.Y, rightB.X, rightB.Y);

          Bitmap img = new Bitmap(scWidth, scHeight, PixelFormat.Format32bppArgb);
          using (Graphics g = Graphics.FromImage(img))
          {
            IActiveView actView = (IActiveView)map;
            tagRECT tag = new tagRECT();
            tag.left = tag.top = 0;
            tag.right = scWidth;
            tag.bottom = scHeight;

            actView.Output(g.GetHdc().ToInt32(), 96, ref tag, env, null);
          }
          return img;
        }
      }, i);

      drawTask.Add(t);
    }
    //}//end map loop
    drawTask.Reverse();
    using (Graphics gra = Graphics.FromHdc((IntPtr)Display.hDC))
    {
      foreach (var t in drawTask)
      {
        using (Bitmap img = t.Result)
        {
          gra.DrawImageUnscaled(img, rect.top, rect.left);
        }
        t.Dispose();

      }//end loop
    }//end graphics

    //drawTask.Reverse();
    //var tArray = drawTask.ToArray();
    //using (var img = tArray[0].Result)
    //{
    //  using (Graphics g = Graphics.FromImage(img))
    //  {
    //    for (int i = 1; i < tArray.Length; i++)
    //    {
    //      Bitmap draw = tArray[i].Result;
    //      g.DrawImageUnscaled(draw, new Rectangle(0, 0, draw.Width, draw.Height));
    //    }
    //  }
    //  using (Graphics gra = Graphics.FromHdc((IntPtr)Display.hDC))
    //  {
    //    gra.DrawImageUnscaled(img, rect.top, rect.left);
    //  }
    //}

  }//end method

}//end class
カテゴリー: 開発 タグ: パーマリンク