最新文章: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 mybatis 3 3.2 3.3  3.4 新特性attilax总结

    Atitit mybatis 3 3.2 3.3  3.4 新特性attilax总结 1.1. iBATIS 3 内的新特性.html1 1.2. MyBatis团队于2013年2月21日正式发布 M ...

  2. 常用sql自定义函数

    --把数字转为千分位格式的字符串显示,调用如 select dbo.f_splitstr(11111111111111) CREATE FUNCTION [dbo].[f_splitstr]( @st ...

  3. 开发中遇到的一些mongoose的问题

    save方法,这个方法可以用来创建新的文档,也可以用来修改已有文档 1,save创建新文档 var Tank = mongoose.model('Tank', yourSchema); 2 var s ...

  4. 转:\r,\n,\r\n的区别

    回车.换行的区别   他们间的区别其实是个回车换行的问题 先来段历史 回车”(Carriage Return)和“换行”(Line Feed)这两个概念的来历和区别. 符号        ASCII码 ...

  5. 乐观锁的一种实现方式—CAS

    线程安全 众所周知,Java是多线程的.但是,Java对多线程的支持其实是一把双刃剑.一旦涉及到多个线程操作共享资源的情况时,处理不好就可能产生线程安全问题.线程安全性可能是非常复杂的,在没有充足的同 ...

  6. 技术范儿的 Keep 发力AI赛道,为什么“虚拟教练”会更懂你?

    http://www.tmtpost.com/3363367.html 摘要: 虚拟教练技术会整合到一些业务场景和硬件产品中收费,但是收费的具体情况彭跃辉还暂未透露. 图片来源于Unsplash 自去 ...

  7. 由于出现以下异常,无法生成模型:“System.Data.StrongTypingException: 表“TableDetails”中列“IsPrimaryKey”的值为 DBNull。

    Entity Framework (version 6.0.0.0) and MySQL Server (>= 5.7.11) 在使用EF中,从数据库中更新模型 操作.报错! 解决办法: 1. ...

  8. (原创)c++11改进我们的模式之改进单例模式

    我会写关于c++11的一个系列的文章,会讲到如何使用c++11改进我们的程序,本次讲如何改进我们的模式,会讲到如何改进单例模式.观察者模式.访问者模式.工厂模式.命令模式等模式.通过c++11的改进, ...

  9. 【Redis】Redis的基本安装及使用、Jedis的基本使用、spring-data-redis的集成、主从模式、哨兵模式

    在Linux上安装Redis Redis的安装很简单.基本上是下载.解压.运行安装脚本.我用的Redis版本是3.2.1. [nicchagil@localhost app]$ wget -q htt ...

  10. webpack的代码分割/离

    两种方法: 1.webpack的methods----require.ensure 2.ES 2015的Loader spec //require.ensure语法 require.ensure [] ...