Winform實現用多線程、百度地圖API解析某公司的物理地址


前言

     作為一個很挫的C#新手總喜歡自己寫點兒不着邊際的東西,本人是個新手加菜鳥,寫B/S的,工作中,任務完成了,空閑下來,總想繼續學點兒什么,由此觸發了本篇文章了。個人一直認為,.NET中,C/S所要求的技術含量要高得多,需要的知識也多得多。所以想多多研究研究。菜鳥文章!

環境

     .NET3.5 + VS2010 + Geocoding API v2.0 +httpwebrequest/httpwebresponse

軟件截圖

這是軟件總圖,很簡單,就幾個按鈕。。。

這里編寫了一個批量導入Excel文件的功能,導入的Excel表內容如下:

導入Excel后,點擊解析,解析出該公司的地理位置、經緯度、精確度、附近地標 and so on~~

解析完成后,支持將結果導出到Excel文件,導出的結果如下圖:

主要是學習百度地圖API、多線程的,所以沒有精心設計皮膚,很朴素啦~~~

代碼部分

     百度地圖API

     接下來說說是如何實現的,其實原理很簡單(我也不會難的。囧。),先調用百度API接口(正向解析),將公司名發送過去,然后會返回一段Json,里面包含了該地址的經緯度,然后繼續調用API(逆向解析),將經緯度發送過去,返回的Json中就包含了地理位置還有一系列其他內容,通過截取之類的操作就得到了我需要的內容。

        /// <summary>
        /// 地址逆向解析
        /// </summary>
        /// <param name="AddressName"></param>
        public DataRow FindAddress(string AddressName, int i, DataRow dr)
        {
            try
            {
                string retString = HttpPost(string.Format("http://api.map.baidu.com/geocoder/v2/?ak=秘鑰&callback=renderOption&output=json&address={0}&city=北京市&precise=1", AddressName));
                retString = retString.Remove(0, 27).TrimEnd(')') + "\r\n";
                string[] strs1 = retString.Split('{');
                string[] strs2 = strs1[3].Split(',');
                string str3 = strs2[0].Split(':')[1];
                string str4 = strs2[1].Split(':')[1].TrimEnd('}');
                string str5 = strs2[3].Split(':')[1];
                this.t_returnString.AppendText("經度:" + str3 + "\r\n" + "緯度:" + str4 + "\r\n" + "精確度:" + str5 + "\r\n");
                string retLocad = HttpPost(string.Format("http://api.map.baidu.com/geocoder/v2/?ak=秘鑰&callback=renderReverse&location={0}&output=json&pois=0", str4 + "," + str3));
                //this.t_returnString.AppendText(retLocad + "\r\n");
                string[] strs1_1 = retLocad.Split('{');
                string[] strs2_1 = strs1_1[3].Split(',');
                string str3_1 = strs2_1[2].Split(':')[1];
                string str4_1 = strs2_1[3].Split(':')[1] + "" + strs2_1[4] + "" + strs2_1[5];
                this.t_returnString.AppendText("地理位置:" + str3_1 + "\r\n");
                this.t_returnString.AppendText("附近地標:" + str4_1 + "\r\n");
                this.t_returnString.ScrollToCaret();//滾動到光標處
                dr["地理位置"] = str3_1;
                dr["附近地標"] = str4_1;
                dr["可信度"] = str5;
            }
            catch (Exception)
            {
                this.t_returnString.AppendText("暫無" + "\r\n");
            }
            return dr;
        }

 

     多線程

     當我完成百度地圖部分后,我決定給自己的小軟件加入批量解析功能,於是乎,出現了導入和導出Excel的功能,這個功能這里不多說,我的博客里面目前為止,基本上都是導入導出(繼續 。囧囧。)。

     當完成批量功能后,發現一執行解析,軟件就假死狀態,突然想起要用多線程。以前沒用過多線程,繼續百度一下,這方面的內容博客園里面挺多的。

        private void b_toExcel_Click(object sender, EventArgs e)
        {
            this.t_txtInfo.Enabled = false;
            this.button1.Enabled = false;
            this.b_openexcel.Enabled = false;
            this.b_toExcel.Enabled = false;
            WhileDataTable = ToDataTable(this.tb_url.Text, 0, true);
            //多線程啟動
            ThreadStart startDownload = new ThreadStart(WhileFunc);
            Thread downloadThread = new Thread(startDownload); //實例化要開啟的新類
            downloadThread.IsBackground = true;
            downloadThread.Start();//開啟線程
        }

      經過上面的部分是啟動多線程的代碼,意外的發現,多線程其實很好弄。

      不過,再次遇到問題,發現交給線程處理的方法,不能傳遞值進行,也就是需要進行線程資源共享,繼續百度!

      這里,我使用委托、創建類級變量共享資源,具體代碼如下(不知道是否理解錯了,若是有錯誤,希望能提點一二):

        private delegate void DoDataDelegate();  //創建委托
        private DataTable WhileDataTable = null; //全局變量
        private DataTable ReturnTable = null;
        public void WhileFunc()
        {
            if (progressBar1.InvokeRequired)
            {
                DoDataDelegate d = WhileFunc;
                progressBar1.Invoke(d, null);
            }
            else
            {
                ReturnTable = new DataTable();
                ReturnTable.Columns.Add("公司名", typeof(string));
                ReturnTable.Columns.Add("可信度", typeof(string));
                ReturnTable.Columns.Add("地理位置", typeof(string));
                ReturnTable.Columns.Add("附近地標", typeof(string));

                progressBar1.Maximum = (int)WhileDataTable.Rows.Count;
                for (int i = 0; i < (int)WhileDataTable.Rows.Count; i++)
                {
                    DataRow row = ReturnTable.NewRow();
                    progressBar1.Value = i + 1;
                    row["公司名"] = WhileDataTable.Rows[i][0];
                    this.t_returnString.AppendText("\r\n" + WhileDataTable.Rows[i][0] + ":\r\n");
                    row = FindAddress(WhileDataTable.Rows[i][0].ToString(), i, row);

                    Application.DoEvents();
                    ReturnTable.Rows.Add(row);
                    if (progressBar1.Value == progressBar1.Maximum)
                    {
                        this.Enabled = true;
                        if (MessageBox.Show("數據解析完成,是否生成Excel文檔?", "消息", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.OK)
                        {
                            CreateSheet("地址解析結果", ReturnTable);
                        }
                    }
                }
            }
        }

到這里,測試,OK!

UI線程和執行方法的線程分離了,軟件UI不會在執行解析方法的時候假死了!

后記

     其實,這個軟件有很大問題的,百度的API並不能准確的返回查詢的公司信息,百度也不可能將所有的公司信息加載到他們的數據庫里面去的。所以精確度有限,實用性差,練手吧!不過,在這個軟件的啟發下,我萌生了繼續開發的想法,這次索性換了一種方法,決定用爬蟲技術+多線程去爬行百度檢索出來的網站,再通過網站內容檢索、跳轉找到這些公司的主頁、或者相關頁面,進一步得到該公司的准確地址信息!

     網絡爬蟲的資料網上不是很多,大部分都是自己琢磨的,某些地方肯定會存在問題,軟件我也寫的差不多了,確實能夠找到公司的具體地理位置,但是還是存在許多問題的。

先貼一張圖,以后有時間完善了,發篇博文上來!

 

相關資料:

百度地圖Geocoding API v2.0:http://developer.baidu.com/map/webservice-geocoding.htm

這里發上源代碼(VS2010工程):http://download.csdn.net/detail/a406502972/7963037


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM