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; }));
                }));
            }
  • 相关阅读:
    Selenium WebDriver-actionchain模拟键盘左键长按
    Selenium WebDriver-actionchain模拟鼠标右键操作
    CSS3 box-sizing:content-box | border-box
    gulp 使用指南
    MAC 使用指南
    移动端布局Rem
    JS面向对象编程
    webstorm 使用指南
    js 获取 touch length
    css 内容居中
  • 原文地址:https://www.cnblogs.com/mawanglin2008/p/3181091.html
Copyright © 2011-2022 走看看