发表用户:protorock
收集整理:James.Liu
相关讨论:http://www.mygis.com.cn/forum/dispbbs.asp?boardID=23&ID=12682
信息原始来源:原创

文章标题:MapXtreme2005桌面程序中多线程更新MapControl的方法

1、问题的提出
在桌面应用中,经常需要用后台线程处理数据,然后将数据更新到地图上显示。
由于MapInfo.Engine内部线程管理机制,从主线程(也就是创建MapControl控件实例的线程)之外的线程不能直接调用MapInfo.Engine.Session.Current.Catalog来获取地图的编录。

2、解决方法
 利用 mapControl1.InvokeRequired 检测是否需要通过Invoke机制更新mapContrl1控件。当对mapControl1更新的调用方位于创建mapControl1控件所在的线程以外的线程时mapControl1.InvokeRequired  = true

3、示例
-------------------------------------------------------------
后台线程:采集GPS定位信息并更新地图
-------------------------------------------------------------
/// <summary>
/// 采集 GPS 定位信息的类
/// </summary>
public class GPS
{
 public delegate void OnNewPositionInfoHandler( float lati, float longti);
 public event NewPositionInfoHandler  OnNewPositionInfo;
  
 private int m_interval;

 /// <summary>
 /// 构造函数
 /// </summary>
 /// <param name="interval">定时更新时间间隔(毫秒)</param>
 public GPS(int interval)
 {
  m_interval = interval;
  Thread t = new Thread(new ThreadStart(WorkThread));
  t.IsBackground = true;
  t.Start();
 }

  
 /// <summary>
 /// 后台线程。接收并处理来自GPS的定位信息并更新地图
 /// </summary>
 private void WorkThread()
 {
      while(true)
      {
            Thread.Sleep(m_interval);

            //这里只是模拟采集到来自GPS的定位信息
            float longi = 32.120201010;
            float lati = 118.39312781;
    
            // 引发事件更新地图
             if(OnNewNewPositionInfo != null) 
                                    OnNewPositionInfo( lati, longti);
      }
 }
}


-------------------------------------------------------------
在Windows窗体代理中
-------------------------------------------------------------

private GPS gps = null;
public delegate UpdateInfoHandler( float lati, float longti);

private void Form1_Load(object sender, System.EventArgs e)
{
  gps = new GPS( 1000 );  // 1秒钟更新一次
    gps.OnNewPositionInfo +=new GPS.OnNewPositionInfo(Form1_OnNewNewPositionInfo );
}

private void Form1_OnNewPositionInfo( float lati, float longti)
{
   if(mapControl1.InvokeRequired)
    {
        object[] para = {lati, longti};
        mapControl1.BeginInvoke( new UpdateInfoHandler(UpdateInfo), para);
   }
  else
     UpdateInfo( lati, longti);


void UpdateInfo( float lati, float longti)
{
   MIConnection cnx =  new MIConnection();
  try
  {
     cnx.Open();
    MICommand cmd = cnx.CreateCommand();
   cmd.CommandText =   string.Format("update s3064 set latitude = {0}, longtitude={1}  ", lati, longti);
   cmd.ExecuteNonQuery();
   mapControl1.Map.Layers[0].Invalidate();
  }
  catch{}
  finally
  {
 cnx.Close();
  }
}