0

I have actually the following code:

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;
    });
}

My problem is that in a previous version without the outer thread, the whole GUI freezes sporadically and the GUI is liquid when the download is finished. So I googled around and found this: https://stackoverflow.com/a/9459441/2288470

An answer was to pack everything into a separate thread which performs the interaction with DownloadFileAsync, but I got the fault, that the BeginInvoke method can not be found.

Community
  • 1
  • 1
Seb Krae
  • 311
  • 3
  • 10

2 Answers2

1

When using WPF, the BeginInvoke method is not exposed by the Window class, like it is for Form in WinForms. Instead you should use Dispatcher.BeginInvoke.


Working code:

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;
    });
}
ebb
  • 9,297
  • 18
  • 72
  • 123
0

Invoke method and BeginInvoke method is implemented on System.Windows.Forms.Control Class. If you are not writing code in such as Form Class, you cannot use this method. To resolve this problem, inherit your Job Class from System.Windows.Forms.Control Class, then you could use BeginInvoke method. Please note that you have to create instance on main thread.

public class JobClass : System.Windows.Forms.Control {
.....
}
Darksanta
  • 166
  • 1
  • 2