WPF换肤之七:异步
在WinForm時(shí)代,相信大家都遇到過這種情形,如果在程序設(shè)計(jì)過程中遇到了耗時(shí)的操作,不使用異步會(huì)導(dǎo)致程序假死。當(dāng)然,在WPF中,這種情況也是存在的,所以我們就需要尋找一種解決方法來讓程序界面響應(yīng)和耗時(shí)操作異步進(jìn)行,那么上述假死的情況就不會(huì)發(fā)生了。
這一節(jié)就著重講解異步以及線程和界面交互。
異步使用方式(APM模式)
在上節(jié)中,我們給一個(gè)普通的Window窗口做了換膚處理,呈現(xiàn)出了一個(gè)非常酷的時(shí)區(qū)瀏覽小工具。當(dāng)然,這一節(jié),我們還是以那個(gè)工具為主,為其增加天氣預(yù)報(bào)功能,而天氣預(yù)報(bào)的數(shù)據(jù)來源,則通過WebService來獲取。
首先,我們?cè)诔绦蛑刑砑覹ebService服務(wù)引用,添加效果如下圖所示,我們需要用到其中的GetWeatherByCityName方法來獲取天氣預(yù)報(bào)信息。
添加完成后,我們就可以通過下面的代碼來獲取城市的天氣信息:
View Code static WeatherWebServiceSoapClient weatherClient; //獲取氣象信息的WebService對(duì)象 private string[] GetWeather(string cityName) {string[] weatherInfoList = null;if (weatherClient == null) weatherClient = new WeatherWebServiceSoapClient("WeatherWebServiceSoap"); //實(shí)例化服務(wù)調(diào)用try{weatherInfoList = weatherClient.getWeatherbyCityName(cityName);}catch (System.Net.WebException webException){throw webException;}catch (System.Net.Sockets.SocketException socketException){throw socketException;}catch (System.NullReferenceException nullException){throw nullException;}catch (System.Exception exception){throw exception;}finally{if (weatherClient != null) weatherClient = null;}return weatherInfoList; }返回的數(shù)組中包含的數(shù)據(jù)信息如下:
View Code #region content //<string>直轄市</string> //<string>上海</string> //<string>58367</string> //<string>58367.jpg</string> //<string>2012-8-10 23:58:13</string> //<string>27℃/33℃</string> //<string>8月11日 陣雨轉(zhuǎn)多云</string> //<string>東南風(fēng)4-5級(jí)</string> //<string>3.gif</string> //<string>1.gif</string> //<string>今日天氣實(shí)況:氣溫:28℃;風(fēng)向/風(fēng)力:北風(fēng) 1級(jí);濕度:80%;空氣質(zhì)量:良;紫外線強(qiáng)度:中等</string> //<string>穿衣指數(shù):天氣炎熱,建議著短衫、短裙、短褲、薄型T恤衫、敞領(lǐng)短袖棉衫等清涼夏季服裝。 感冒指數(shù):暫無。 運(yùn)動(dòng)指數(shù):有降水,風(fēng)力較強(qiáng),較適宜在戶內(nèi)開展低強(qiáng)度運(yùn)動(dòng),若堅(jiān)持戶外運(yùn)動(dòng),請(qǐng)選擇避雨防風(fēng)地點(diǎn)。 洗車指數(shù):不宜洗車,未來24小時(shí)內(nèi)有雨,如果在此期間洗車,雨水和路上的泥水可能會(huì)再次弄臟您的愛車。 晾曬指數(shù):有降水,可能會(huì)淋濕晾曬的衣物,不太適宜晾曬。請(qǐng)隨時(shí)注意天氣變化。 旅游指數(shù):有陣雨,氣溫較高,但風(fēng)較大,能緩解濕熱的感覺,還是適宜旅游,您仍可陶醉于大自然的美麗風(fēng)光中。 路況指數(shù):有降水,路面潮濕,車輛易打滑,請(qǐng)小心駕駛。 舒適度指數(shù):天氣較熱,雖然有降水,但仍然無法削弱較高氣溫給人們帶來的暑意,這種天氣會(huì)讓您感到不很舒適。 空氣污染指數(shù):氣象條件有利于空氣污染物稀釋、擴(kuò)散和清除,可在室外正常活動(dòng)。 紫外線指數(shù):屬中等強(qiáng)度紫外線輻射天氣,外出時(shí)建議涂擦SPF高于15、PA+的防曬護(hù)膚品,戴帽子、太陽鏡。</string> //<string>27℃/34℃</string> //<string>8月12日 多云</string> //<string>南風(fēng)3-4級(jí)</string> //<string>1.gif</string> //<string>1.gif</string> //<string>28℃/34℃</string> //<string>8月13日 陣雨</string> //<string>南風(fēng)3-4級(jí)</string> //<string>3.gif</string> //<string>3.gif</string> //<string>上海簡(jiǎn)稱:滬,位置:上海地處長(zhǎng)江三角洲前緣,東瀕東海,南臨杭州灣,西接江蘇,浙江兩省,北界長(zhǎng)江入海,正當(dāng)我國(guó)南北岸線的中部,北緯31°14′,東經(jīng)121°29′。面積:總面積7823.5平方公里。人口:人口1000多萬。上海豐富的人文資源、迷人的城市風(fēng)貌、繁華的商業(yè)街市和歡樂的節(jié)慶活動(dòng)形成了獨(dú)特的都市景觀。游覽上海,不僅能體驗(yàn)到大都市中西合壁、商儒交融、八方來風(fēng)的氛圍,而且能感受到這個(gè)城市人流熙攘、車水馬龍、燈火璀璨的活力。上海在中國(guó)現(xiàn)代史上占有著十分重要的地位,她是中國(guó)**黨的誕生地。許多震動(dòng)中外的歷史事件在這里發(fā)生,留下了眾多的革命遺跡,處處為您講述著一個(gè)個(gè)使人永不忘懷的可歌可泣的故事,成為包含民俗的人文景觀和紀(jì)念地。在上海,每到秋祭,紛至沓來的人們?cè)谶@里祭祀先烈、緬懷革命歷史,已成為了一種風(fēng)俗。大上海在中國(guó)近代歷史中,曾是風(fēng)起云涌可歌可泣的地方。在這里薈萃多少風(fēng)云人物,散落在上海各處的不同住宅建筑,由于其主人的非同尋常,蘊(yùn)含了耐人尋味的歷史意義。這里曾留下許多革命先烈的足跡。瞻仰孫中山、宋慶齡、魯迅等故居,會(huì)使您產(chǎn)生撫今追昔的深沉遐思,這里還有無數(shù)個(gè)達(dá)官貴人的住宅,探訪一下李鴻章、蔣介石等人的公館,可以聯(lián)想起主人那段顯赫的發(fā)跡史。</string> #endregion現(xiàn)在,問題來了,如果我們?cè)诔绦蛑兄苯诱{(diào)用這個(gè)接口來獲取天氣信息的話,會(huì)發(fā)現(xiàn)主界面快則五六秒,慢則二十秒后才能夠顯現(xiàn)出來,這就說明,當(dāng)程序獲取天氣信息的時(shí)候,主界面被阻塞住了。為什么會(huì)被阻塞,是因?yàn)槌绦虮旧碇挥幸粭l主線程,當(dāng)程序獲取天氣信息的時(shí)候,線程占用,界面顯示當(dāng)然不能進(jìn)行了。解決方法就是使用異步。
關(guān)于異步的文章,請(qǐng)參看我之前的這篇博文:我所知道的.NET異步, 由于我是APM模式(就是BeginXXXX和EndXXXX成對(duì)出現(xiàn))的忠實(shí)粉絲,所以采用的代碼如下:
View Code private void BeginInvokeWeather(string citiName) {try{Func<string, string[]> func = new Func<string, string[]>(GetWeather);IAsyncResult iar = func.BeginInvoke(citiName, new AsyncCallback(EndInvokeWeather), func);lblLoadingText.Dispatcher.Invoke(new Action(delegate(){lblLoadingText.Opacity = 1;lblLoadingText.Content = "加載天氣中...";}));}catch(Exception ex){throw ex;} }private void EndInvokeWeather(IAsyncResult iar) {Func<string, string[]> func = (Func<string, string[]>)iar.AsyncState; //還原狀態(tài)string[] weatherDaemonList = func.EndInvoke(iar); //獲取值weatherInfoParamValue = weatherDaemonList;if (weatherDaemonList != null){if (weatherDaemonList.Length > 0) //獲取成功 {//進(jìn)行處理if (weatherDaemonList.Length < 9) return;string imgNameWithoutExtension = GetImgNameWithOutExtension(weatherDaemonList[8]);if (!imgNameWithoutExtension.Equals("NA")) isSuccess = true;string uriStringParam = "pack://application:,,,/TimeZoneDaemonApp;component/Images/Weather/" + imgNameWithoutExtension + ".png";//重新初始化一下,避免多次加載造成的資源沖突weatherImg.Dispatcher.Invoke(new Action(delegate(){weatherImg = new BitmapImage();}));weatherImg.Dispatcher.Invoke(new Action(delegate(){weatherImg.BeginInit();weatherImg.UriSource = new Uri(uriStringParam);weatherImg.EndInit();DayMark.Width = weatherImgWidth;DayMark.Height = weatherImgHeight;DayMark.Source = weatherImg;lblLoadingText.Content = "調(diào)用結(jié)束...";lblLoadingText.Opacity = 0;}));}}}這樣,當(dāng)程序啟動(dòng)的時(shí)候,便會(huì)異步獲取天氣信息,界面阻塞的問題得以解決,請(qǐng)看圖示:
加載完成之后,我們就可以看到原來現(xiàn)在我在的地方是朗朗晴天呢... :D
當(dāng)然,這里還涉及到一個(gè)問題,就是線程和UI交互的問題,在Winform中我們可以通過Control.Invoke的方式來進(jìn)行,在WPF中,只是多了一個(gè)Dispatcher而已,具體用法就是Control. Dispatcher.Invoke來進(jìn)行,比如加載天氣的Label就是利用這種方式進(jìn)行交互的:
View Code lblLoadingText.Dispatcher.Invoke(new Action(delegate() {lblLoadingText.Opacity = 1;lblLoadingText.Content = "加載天氣中..."; }));希望本文對(duì)你有用。
?源碼下載
點(diǎn)擊這里下載源碼?? 由于工程中圖片體積太大,就拿出來單獨(dú)上傳,用的時(shí)候直接覆蓋掉Images文件夾即可。?點(diǎn)擊這里下載資源文件
轉(zhuǎn)載于:https://www.cnblogs.com/scy251147/archive/2012/08/11/2634078.html
總結(jié)
以上是生活随笔為你收集整理的WPF换肤之七:异步的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pku 1691 Painting A
- 下一篇: 将csv文件导入到数据库中