前一篇小豬分享過在WPF中簡單的使用BackgroundWorker完成多線程操作!在那篇中小豬利用了BackgroundWorker組件對耗時比較多的操作放在了單獨的BackgroundWorker里來完成,例如說:網絡請求的登錄操作,說到網絡請求當然還有另外一種請求:網絡下載。
當客戶端需要進行網絡下載操作時如果只是簡單的用多線程這么一個操作而不給用戶知道當前的下載進度的話那么用戶將不知道已經下載了多少,甚至有可能直接關閉了主應用程序。那就杯具了。
這時候就涉及到在另外的線程中來更新UI,但是WPF卻明確的規定:UI元素只能由其主線程來操作,其他任何線程都不可以直接操作UI。而實時的下載進度又不能通過調用某個回調函數來完成更新UI。
這時候就是Dispatcher.Invoke方法上場的時間了
下面代碼實現了我們想要的功能:
private delegate void SetTipsValue_dg(long solength, long stlength); private void SetTipsValue(long solength, long stlength) { block_Tips.Text = "下載中...." + solength + "/" + stlength; }
private bool DownloadFile(string URL, string filename) { try { System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(URL); System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); System.IO.Stream st = myrp.GetResponseStream(); long stll = myrp.ContentLength; System.IO.Stream so = new System.IO.FileStream(filename, System.IO.FileMode.Create); byte[] by = new byte[1024]; int osize = st.Read(by, 0, (int)by.Length); while (osize > 0) { long sol = so.Length; long stl = stll; this.block_Tips.Dispatcher.Invoke(new SetTipsValue_dg(SetTipsValue), sol, stl); so.Write(by, 0, osize); osize = st.Read(by, 0, (int)by.Length); } so.Close(); st.Close(); myrp.Close(); Myrq.Abort(); return true; } catch (System.Exception e) { return false; } }
上面代碼首先定義了一個委托:該委托接受兩個參數分別代表當前下載量和總下載量,然后定義了一個具體的實現該委托的方法,該方法調用UI來顯示數據。
在下載數據的主函數DownloadFile中調用了this.block_Tips.Dispatcher.Invoke方法並將實現了委托的方法SetTipsValue方法和當前下載量及總下載量的數值傳進去我們就完成了整個操作。這樣我們在下載數據的時候用另外的線程開啟了DownloadFile方法就可以實時的顯當前的下載進度了。
