【问题标题】:Creating a multi-thread webdownload via WebClient / BeginInvoke Method通过 WebClient / BeginInvoke 方法创建多线程 webdownload
【发布时间】:2013-04-16 22:54:06
【问题描述】:

我实际上有以下代码:

private Stopwatch _sw;

public void DownloadFile(string url, string fileName)
{
    string path = @"C:\DL\";

    Thread bgThread = new Thread(() =>
    {

        _sw = new Stopwatch();
        _sw.Start();
        labelDownloadAudioStatusText.Visibility = Visibility.Visible;
        using (WebClient webClient = new WebClient())
        {
            webClient.DownloadFileCompleted +=
                new AsyncCompletedEventHandler(DownloadCompleted);
            webClient.DownloadProgressChanged +=
                new DownloadProgressChangedEventHandler(DownloadStatusChanged);
            webClient.DownloadFileAsync(new Uri(url), path + fileName);
        }
    });

    bgThread.Start();
}

void DownloadStatusChanged(object sender, DownloadProgressChangedEventArgs e)
{
    this.BeginInvoke((MethodInvoker) delegate
    {
        int percent = 0;
        if (e.ProgressPercentage != percent)
        {
            percent = e.ProgressPercentage;
            progressBarDownloadAudio.Value = percent;

            labelDownloadAudioProgress.Content = percent + "%";
            labelDownloadAudioDlRate.Content =
                (Convert.ToDouble(e.BytesReceived)/1024/
                _sw.Elapsed.TotalSeconds).ToString("0.00") + " kb/s";

            Thread.Sleep(50);
        }
    });
}

private void DownloadCompleted(object sender, AsyncCompletedEventArgs e)
{
    this.BeginInvoke((MethodInvoker) delegate
    {

        labelDownloadAudioDlRate.Content = "0 kb/s";
        labelDownloadAudioStatusText.Visibility = Visibility.Hidden;
    });
}

我的问题是,在没有外线程的先前版本中,整个 GUI 偶尔会冻结,并且在下载完成时 GUI 是流动的。所以我搜索了一下,发现了这个:https://stackoverflow.com/a/9459441/2288470

答案是将所有内容打包到一个单独的线程中,该线程执行与DownloadFileAsync 的交互,但我遇到了错误,找不到BeginInvoke 方法。

【问题讨论】:

  • 你想在你的Form 课堂上打电话给this.BeginInvoke 吗?
  • 是的,但是如何在 WPF 项目中使用它?

标签: c# wpf multithreading asynchronous


【解决方案1】:

使用 WPF 时,Window 类不会公开 BeginInvoke 方法,就像 WinForms 中的 Form 一样。相反,您应该使用Dispatcher.BeginInvoke。


工作代码:

private Stopwatch _sw;

public void DownloadFile(string url, string fileName)
{
    string path = @"C:\DL\";

    Thread bgThread = new Thread(() =>
    {
        _sw = new Stopwatch();
        _sw.Start();
        labelDownloadAudioStatusText.Visibility = Visibility.Visible;
        using (WebClient webClient = new WebClient())
        {
            webClient.DownloadFileCompleted +=
                new AsyncCompletedEventHandler(DownloadCompleted);
            webClient.DownloadProgressChanged +=
                new DownloadProgressChangedEventHandler(DownloadStatusChanged);
            webClient.DownloadFileAsync(new Uri(url), path + fileName);
        }
    });

    bgThread.Start();
}

void DownloadStatusChanged(object sender, DownloadProgressChangedEventArgs e)
{
    Dispatcher.BeginInvoke((MethodInvoker) delegate
    {
        int percent = 0;

        if (e.ProgressPercentage != percent)
        {
            percent = e.ProgressPercentage;
            progressBarDownloadAudio.Value = percent;

            labelDownloadAudioProgress.Content = percent + "%";
            labelDownloadAudioDlRate.Content =
                (Convert.ToDouble(e.BytesReceived)/1024/
                _sw.Elapsed.TotalSeconds).ToString("0.00") + " kb/s";

            Thread.Sleep(50);
        }
    });
}

private void DownloadCompleted(object sender, AsyncCompletedEventArgs e)
{
    Dispatcher.BeginInvoke((MethodInvoker) delegate
    {
        labelDownloadAudioDlRate.Content = "0 kb/s";
        labelDownloadAudioStatusText.Visibility = Visibility.Hidden;
    });
}

【讨论】:

    【解决方案2】:

    Invoke 方法和 BeginInvoke 方法在 System.Windows.Forms.Control 类上实现。如果您不是在 Form Class 中编写代码,则不能使用此方法。要解决此问题,请从 System.Windows.Forms.Control 类继承您的作业类,然后您可以使用 BeginInvoke 方法。请注意,您必须在主线程上创建实例。

    public class JobClass : System.Windows.Forms.Control {
    .....
    }
    

    【讨论】:

    • 如何在 WPF 项目中使用它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    相关资源
    最近更新 更多