通过WebClient / BeginInvoke方法创建多线程webdownload

本文关键字:创建 多线程 webdownload 方法 BeginInvoke WebClient 通过 | 更新日期: 2023-09-27 18:09:28

我实际上有以下代码:

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方法。

通过WebClient / BeginInvoke方法创建多线程webdownload

当使用WPF时,BeginInvoke方法不被Window类暴露,就像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;
    });
}

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

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