最新文章: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; })); })); }