最新文章:Virson's Blog

首先要感谢yk000123的慷慨开源,开源地址见:http://doubanfm.codeplex.com/

最近正好在学习WPF,然后在Codeplex上找到了用WPF写的DoubanFM的客户端,抱着练练手的心态,着手研究代码,研究了一段时间后,准备自己加一个新功能(新功能是关于下载的,但是由于豆瓣官方版权的原因,抱歉没法为博友们提供下载,敬请谅解),于是就有了如下的问题:

在使用ThreadPool.QueueUserWorkItem()方法开始后台下载歌曲的时候,无法禁用UI界面上的下载按钮。

遇到问题和广大码农想法一样,先搜索试试看(可怜的Google):

然后找到了两篇文章,引用一下:博客园-大传神CSDN-yikai2009,在此感谢两位博主的倾情付出!

问题描述:由于其他线程拥有此对象,因此调用线程无法对其进行访问 (The calling thread cannot access this object because a different thread owns it)

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

Invoke 是同步操作;因此,直到回调返回之后才会将控制权返回给调用对象

最终实现代码:

        /// <summary>
/// 使用异步和断点续传的方式下载歌曲
/// </summary>
private void StartDownloadSongs()
{
//DownloadSearch.Search(_player.CurrentSong.Title, _player.CurrentSong.Artist, _player.CurrentSong.Album);
//BassEngine.Instance.OpenUrlAsync(_player.CurrentSong.FileUrl);
string currentSongFileUrl = _player.CurrentSong.FileUrl;
string downSavePath = DownSaveSetting.DownSavePath;
int currentSongTypePoint = currentSongFileUrl.LastIndexOf('.');
string currentSongType = currentSongFileUrl.Substring(currentSongTypePoint, currentSongFileUrl.Length - currentSongTypePoint); string strFileName = string.Empty; //包含路径的歌曲名
string currentSongTitle = _player.CurrentSong.Title.Replace("/", "&"); //当前播放歌曲的歌曲名
string currentSongArtist = _player.CurrentSong.Artist.Replace("/" , "&"); //当前播放歌曲的作者
string currentSongAlbum = _player.CurrentSong.Album.Replace("/", "&"); //当前播放歌曲的专辑 if (DownSaveSetting.IsCreateFolderByArtist)
{
string savePathWithArtist = Path.Combine(downSavePath, currentSongArtist);
if (!Directory.Exists(savePathWithArtist))
Directory.CreateDirectory(savePathWithArtist);
strFileName = savePathWithArtist + "\\" + currentSongArtist + " - " + currentSongTitle + currentSongType;
}
else
{
if (!Directory.Exists(downSavePath))
Directory.CreateDirectory(downSavePath);
strFileName = downSavePath + "\\" + currentSongArtist + " - " + currentSongTitle + currentSongType;
} if (Download.IsExistFile(strFileName))
{
MessageBoxResult result = MessageBox.Show(this,
DoubanFM.Resources.Resources.DownFileIsExistHint,
string.Empty,
MessageBoxButton.OKCancel,
MessageBoxImage.Information);
if (result == MessageBoxResult.OK)
{
//开始文件下载线程
Download.DeleteFile(strFileName);
StartDownloadSongsThread(strFileName, currentSongFileUrl);
}
}
else
{
StartDownloadSongsThread(strFileName, currentSongFileUrl);
}
} private void StartDownloadSongsThread(string strFileName, string strUrl)
{
//开始文件下载线程
ThreadPool.QueueUserWorkItem(new WaitCallback(o =>
{
this.BtnDownload.Dispatcher.BeginInvoke(new Action(delegate() { BtnDownload.IsEnabled = false; }));
if (Download.DownloadFile(strFileName, strUrl))
this.BtnDownload.Dispatcher.BeginInvoke(new Action(delegate() { BtnDownload.IsEnabled = true; }));
}));
}

解决DoubanFM第三方客户端UI线程与工作线程交互问题的更多相关文章

  1. Service的线程、工作线程、权限及系统Service

    Service组件和其他组件一样,都是运行于应用的主线程当中,它们都运行于同一个单一的线程中. 可以把Service简单的理解成一个没有界面显示的Activity(这个比喻其实并不准确,因为Servi ...

  2. android中工作线程安全

    当应用程序启动,创建了一个叫“main”的线程,用于管理UI相关,又叫UI线程.其他线程叫工作线程(Work Thread). Single Thread Model 一个组件的创建并不会新建一个线程 ...

  3. TSQLDBServerHttpApi使用工作线程池

    TSQLDBServerHttpApi使用工作线程池 TSQLDBServerHttpApi创建时,默认是使用单线程模式,且只使用一个数据库连接,服务端要应对众多的客户端只靠一个工作线程(主线程)和一 ...

  4. JAVA之工作线程数究竟要设置多少

    一.需求缘起 Web-Server通常有个配置,最大工作线程数,后端服务一般也有个配置,工作线程池的线程数量,这个线程数的配置不同的业务架构师有不同的经验值,有些业务设置为CPU核数的2倍,有些业务设 ...

  5. ZooKeeper:第三方客户端 ZKClient

    ZKClient ZKClient的设计 ZKClient组件说明 重要的处理流程说明 启动ZKClient 为节点注册Watcher ZooKeeper的变更操作 客户端处理变更 序列化处理 ZKC ...

  6. Android的UI设计与后台线程交互

    本文将讨论Android应用程序的线程模型以及如何使用线程来处理耗时较长的操作,而不是在主线程中执行,保证用户界面(UI)的流畅运行.本文还将阐述一些用户界面(UI)中与线程交互的API.UI用户界面 ...

  7. C# 多线程详解 Part.01(UI 线程、子线程)

    基本概念 什么是进程?        当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.一个进程至少有一个主线程. 什么是线程?        线程是程序中的一 ...

  8. 为什么说android UI操作不是线程安全的

    转载于:http://blog.csdn.net/lvxiangan/article/details/17218409#t2 UI线程及Android的单线程模型原则 使用Worker线程 Commu ...

  9. 转载:IIS 之 连接数、并发连接数、最大并发工作线程数、队列长度、最大工作进程数

    一.IIS连接数 一般购买过虚拟主机的朋友都熟悉购买时,会限制IIS连接数,顾名思义即为IIS服务器可以同时容纳客户请求的最高连接数,准确的说应该叫“IIS限制连接数”. 客户请求的连接内容包括: [ ...

随机推荐

  1. Atitit 爬虫 node版 attilaxA

    Atitit 爬虫 node版 attilax 1.1. 貌似不跟python压实,,java的webmagic压实,,什么爬虫框架也没有,只好自己写了. 查了百度三爷资料也没有.都是自己写.. 1. ...

  2. HTML5 History API让ajax能回退到上一页

    HTML5 History API提供了一种功能,能让开发人员在不刷新整个页面的情况下修改站点的URL.这个功能很有用,例如通过一段JavaScript代码局部加载页面的内容,你希望通过改变当前页面的 ...

  3. (原创)c++11改进我们的模式之改进表驱动模式

    所谓表驱动法(Table-Driven Approach),简单讲是指用查表的方法获取值.表驱动是将一些通过较为复杂逻辑语句来得到数据信息的方式,通过查询表的方式来实现,将数据信息存放在表里.对于消除 ...

  4. angular.js测试框架protracotr自带的webdriver-manager启动问题“Invalid or corrupt jarfile”

    按照官网安装完protractor. 升级webdriver-manager,获取selenium-server-standalone库文件以及各种浏览器驱动文件. webdriver-manager ...

  5. javascript基础拾遗(四)

    1.什么是闭包 正常函数,执行完毕后相关的参数,变量就释放掉了. 当一个函数的返回值是另一个函数时,该函数的相关参数和变量都会保存在返回的函数中,这种结构叫做闭包. 2.示例 计算数组和 functi ...

  6. 每日英语:Missing at Mobile World Congress: Innovation

    The hottest showcase for new technology at this year's Mobile World Congress wasn't in the event's c ...

  7. cc(self)是什么意思?

    分别找到这2句代码:   复制代码 cc(self):addComponent("components.behavior.EventProtocol"):exportMethods ...

  8. 【转】Unity3D的LightProbe动态光探头用法介绍

    原创至上,移步请戳:Unity3D的LightProbe动态光探头用法介绍 之前曾经介绍过Unity3D的LightMapping烘焙的用法.单独使用的LightMapping效果很好,但由于只是把光 ...

  9. 【Android】Sensor框架Framework层解读

    Sensor整体架构 整体架构说明 黄色部分表示硬件,它要挂在I2C总线上 红色部分表示驱动,驱动注册到Kernel的Input Subsystem上,然后通过Event Device把Sensor数 ...

  10. WeakReference 学习和使用

    本文转自:http://qifuguang.me/2015/09/02/[Java%E5%B9%B6%E5%8F%91%E5%8C%85%E5%AD%A6%E4%B9%A0%E4%B8%83]%E8% ...