前一篇小猪分享过在WPF中简单的使用BackgroundWorker完成多线程操作!在那篇中小猪利用了BackgroundWorker组件对耗时比较多的操作放在了单独的BackgroundWorker里来完成,例如说:网络请求的登录操作,说到网络请求当然还有另外一种请求:网络下载。

当客户端需要进行网络下载操作时如果只是简单的用多线程这么一个操作而不给用户知道当前的下载进度的话那么用户将不知道已经下载了多少,甚至有可能直接关闭了主应用程序。那就杯具了。

这时候就涉及到在另外的线程中来更新UI,但是WPF却明确的规定:UI元素只能由其主线程来操作,其他任何线程都不可以直接操作UI。而实时的下载进度又不能通过调用某个回调函数来完成更新UI。

引用:

WPF中的UI控件,如果我们探究本质,他们都是从DispatcherObject继承,所以都必须由UI线程进行调度和使用,如果我们在其他的后台线程中操作界面相关的元素时,就会出现如下的异常信息:
调用线程无法访问此对象,因为另一个线程拥有该对象。

这时候就是Dispatcher.Invoke方法上场的时间了

引用:

在 WPF 中,只有创建 DispatcherObject 的线程才能访问该对象。 例如,一个从主 UI 线程派生的后台线程不能更新在该 UI 线程上创建的 Button 的内容。 为了使该后台线程能够访问 Button 的 Content 属性,该后台线程必须将此工作委托给与该 UI 线程关联的 Dispatcher。
使用 Invoke 或 BeginInvoke 来完成此操作。 Invoke 是同步操作,而 BeginInvoke 是异步操作。 该操作将按指定的 DispatcherPriority 添加到 Dispatcher 的事件队列中。

下面代码实现了我们想要的功能:

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[];
int osize = st.Read(by, , (int)by.Length);
while (osize > )
{
long sol = so.Length;
long stl = stll;
this.block_Tips.Dispatcher.Invoke(new SetTipsValue_dg(SetTipsValue), sol, stl);
so.Write(by, , osize);
osize = st.Read(by, , (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方法就可以实时的显当前的下载进度了。

最新文章

  1. command shell 的知识整理
  2. Servlet 生命周期与web容器的关系
  3. [转]Mac OS X El Capitan(10.11)显示隐藏文件命令失效解决方法
  4. 表单提交与后台PHP如何接口?
  5. 十天冲刺---Day1
  6. javascript设计模式-抽象工厂模式
  7. COUNT(*),count(1),COUNT(ALL expression),COUNT(DISTINCT expression)
  8. Eclipse能否把选中的一段代码向前或向后缩进一个tab的位
  9. 《Programming WPF》翻译 第6章 5.我们进行到哪里了?
  10. Tomcat源码学习一
  11. 走进BFC
  12. GIT入门笔记(10)- 多种撤销修改场景和对策
  13. C# 线程获取/设置控件(TextBox)值
  14. 3ds max学习笔记(六)-- 基本操作(建模前奏)
  15. 5月17 AJAX返回类型-------JSON和XML
  16. Minimum number of steps 805D
  17. 【Alpha】团队项目测试报告与用户反馈
  18. Lomboz插件
  19. 使用SQL语句创建数据库1
  20. py2exe使用总结

热门文章

  1. [xampp]在Crunch Bang下安装xampp1.8.3
  2. cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element ‘dubbo:application’. – schema_reference.4: Failed to read schema document
  3. CentOS7下安装Mysql和Memcached 以及 使用C#操作Mysql和Memcached
  4. calico docker 应用实例
  5. linux查看磁盘系统df,du
  6. 【转】MarshalAs属性和使用
  7. [课程设计]Scrum 2.0 多鱼点餐系统开发进度(第二阶段项目构思与任务规划)
  8. I18N
  9. EF获取一个或者多个字段
  10. find函数