zoukankan      html  css  js  c++  java
  • 解决DoubanFM第三方客户端UI线程与工作线程交互问题

    最新文章: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; }));
                }));
            }
  • 相关阅读:
    实例讲解虚拟机3种网络模式(桥接、nat、Host-only)
    期刊搜索问题——SCI、EI、IEEE和中文期刊
    面向对象分析与设计(C++)课堂笔记
    windows与VMware ubuntu虚拟机实现文件共享
    GDI+在绘制验证码中的使用
    【转】.net中快捷键的使用
    MD5加密“破解”在.NET平台实现最基本的理解
    UE4 Persona 骨架网格物体动画
    从零开始做3D地图编辑器 基于QT与OGRE
    TBB(Intel Threading Building Blocks)学习笔记
  • 原文地址:https://www.cnblogs.com/mawanglin2008/p/3181091.html
Copyright © 2011-2022 走看看