【问题标题】:Report download progress to user interface向用户界面报告下载进度
【发布时间】:2014-12-14 07:42:10
【问题描述】:

我正在开发一个项目,该项目提取 YouTube 视频的音频并将其保存到您的计算机上。 为此,我使用了来自 GitHub 的一个名为 YouTubeExtractor 的库。

我正在使用后台工作程序,以便在下载文件时使 UI 可用。这是我到目前为止的代码。

public partial class MainWindow : Window
{
    private readonly BackgroundWorker worker = new BackgroundWorker();
    public MainWindow()
    {
        InitializeComponent();
        worker.DoWork += worker_DoWork;
        worker.WorkerReportsProgress = true;
        worker.WorkerSupportsCancellation = true;
    }

    private void downloadButton_Click(object sender, RoutedEventArgs e)
    {
        worker.RunWorkerAsync();
    }
    string link;
    double percentage;
    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        this.Dispatcher.Invoke((Action)(() =>
        {
            link = videoURL.Text;
        }));


        /*
         * Get the available video formats.
         * We'll work with them in the video and audio download examples.
         */
        IEnumerable<VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(link);

        /*
         * We want the first extractable video with the highest audio quality.
         */
        VideoInfo video = videoInfos
            .Where(info => info.CanExtractAudio)
            .OrderByDescending(info => info.AudioBitrate)
            .First();

        /*
         * If the video has a decrypted signature, decipher it
         */
        if (video.RequiresDecryption)
        {
            DownloadUrlResolver.DecryptDownloadUrl(video);
        }

        /*
         * Create the audio downloader.
         * The first argument is the video where the audio should be extracted from.
         * The second argument is the path to save the audio file.
         */
        var audioDownloader = new AudioDownloader(video, System.IO.Path.Combine("C:/Downloads", video.Title + video.AudioExtension));

        // Register the progress events. We treat the download progress as 85% of the progress and the extraction progress only as 15% of the progress,
        // because the download will take much longer than the audio extraction.
        audioDownloader.DownloadProgressChanged += (send, args) => Console.WriteLine(args.ProgressPercentage * 0.85);
        audioDownloader.AudioExtractionProgressChanged += (send, args) => Console.WriteLine(85 + args.ProgressPercentage * 0.15);
        /*
         * Execute the audio downloader.
         * For GUI applications note, that this method runs synchronously.
         */
        audioDownloader.Execute();
    }
}

}

我的问题是我想显示这个

      audioDownloader.DownloadProgressChanged += (send, args) => Console.WriteLine(args.ProgressPercentage * 0.85);
      audioDownloader.AudioExtractionProgressChanged += (send, args) => Console.WriteLine(85 + args.ProgressPercentage * 0.15);

在标签或进度条等 UI 元素中,而不是在 Console.WriteLine 中

每当我这样做 label1.Text = (85 + args.ProgressPercentage * 0.15); 时,它都会给我一个类似

的错误

" 调用线程无法访问此对象,因为另一个线程拥有它。"

我知道你可以通过委托来解决这个问题,我需要一个明确的说明。

谢谢。

【问题讨论】:

  • 你已经知道如何解决这个问题了。 this.Dispatcher.Invoke.
  • @SLaks 是的,但是当我尝试用它来解决它时,它给了我更多的错误,我不知道我是在执行这个错误还是......但是,名为“链接”工作完美,因为我从 UI 获取文本,在 UI 上显示不起作用。
  • 阅读错误,并向我们展示您的尝试。此外,使用 BackgroundWorker 并没有任何好处。
  • 您应该使用任务 (msdn.microsoft.com/en-us/library/…),为什么不使用现有基础架构来报告进度 (msdn.microsoft.com/en-us/library/…)?
  • @SLaks 为什么你认为我不应该使用 BackgroundWorker?

标签: c# youtube download background-process


【解决方案1】:

这是使用 Tasks 和 async / await 关键字的现代方法

加上Dispatcher.BeginInvoke 用于更新您的用户界面。

代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using YoutubeExtractor;

namespace WpfApplication1
{
    public partial class MainWindow
    {
        public MainWindow() {
            InitializeComponent();
        }

        private async void Button_Click(object sender, RoutedEventArgs e) {
            string videoUrl = @"https://www.youtube.com/watch?v=5aXsrYI3S6g";
            await DownloadVideoAsync(videoUrl);
        }

        private Task DownloadVideoAsync(string url) {
            return Task.Run(() => {
                IEnumerable<VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(url);
                VideoInfo videoInfo = videoInfos.FirstOrDefault();
                if (videoInfo != null) {
                    if (videoInfo.RequiresDecryption) {
                        DownloadUrlResolver.DecryptDownloadUrl(videoInfo);
                    }

                    string savePath =
                        Path.Combine(
                            Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
                            Path.ChangeExtension("myVideo", videoInfo.VideoExtension));
                    var downloader = new VideoDownloader(videoInfo, savePath);
                    downloader.DownloadProgressChanged += downloader_DownloadProgressChanged;
                    downloader.Execute();
                }
            });
        }

        private void downloader_DownloadProgressChanged(object sender, ProgressEventArgs e) {
            Dispatcher.BeginInvoke((Action) (() => {
                double progressPercentage = e.ProgressPercentage;
                ProgressBar1.Value = progressPercentage;
                TextBox1.Text = string.Format("{0:F} %", progressPercentage);
            }));
        }
    }
}

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Width="525"
        Height="350">
    <Grid>

        <StackPanel>
            <Button Click="Button_Click" Content="Download" />
            <ProgressBar x:Name="ProgressBar1"
                         Height="20"
                         Maximum="100" />
            <TextBox x:Name="TextBox1" />
        </StackPanel>
    </Grid>
</Window>

【讨论】:

  • 完美运行,我调整了代码,现在只下载音频。您对如何提高音频质量有任何想法吗?谢谢。
  • 据我在您的 API 中了解,并非所有视频的音频都可以提取,尤其是高清音频(在我放入代码中的视频上)。你能做什么,抓住高清然后使用 FFMPEG 将流与ffmpeg -i video.mp4 -vn acodec copy audio.aac 之类的东西分开,你会得到最好的质量(详见askubuntu.com/questions/221026/…)。
  • 除此之外,增强音频文件可以使用类似的方法:sound.stackexchange.com/questions/28300/…fxsound.com/dfx。我个人会选择 FFMPEG 解决方案,因为使用 Process.Start (msdn.microsoft.com/en-us/library/…) 实现它是免费且快速的;它也是理想的,因为您可以直接从 Youtube 获得最佳音频,而不是“增强器”。不过,没有什么能阻止你做这两件事:D
  • 你有 Skype 吗?我真的需要一些帮助来更清楚地理解这些程序。我对 FFmpeg 解决方案非常感兴趣,但需要更多说明。谢谢。
  • 不,对不起,我没有。但是你可以问其他问题,在这里通知我,我会回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-24
相关资源
最近更新 更多