【问题标题】:Run background worker in parallel with Webclient file download与 Webclient 文件下载并行运行后台工作程序
【发布时间】:2016-01-22 15:48:25
【问题描述】:

我有一个后台工作程序,用于与服务器运行耗时的同步操作,并且运行良好,并且 UI 在操作期间响应

        BackgroundWorker syncWorker = new BackgroundWorker();
        syncWorker.WorkerReportsProgress = true;            
        syncWorker.DoWork += new DoWorkEventHandler(syncWorker_DoWork);
        syncWorker.ProgressChanged += new ProgressChangedEventHandler(syncWorker_ProgressChanged);
        syncWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(syncWorker_RunWorkerCompleted);
    private void syncWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        foreach (xxxx item in actives)
        {
            target.ReportProgress(progress);
           //time taking event running fine here..
        }
        target.ReportProgress(90);          
    }
    private void syncWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
       lbl_progress.Text="Wait......";
    }

    private void syncWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
       lbl_progress.Text="DONE!..";
    }           

现在我必须做一个文件下载操作,我正在使用 Webclient 使用代码来做它

            WebClient  downloadClient = new WebClient();
            downloadClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(downloadClient_DownloadProgressChanged);
            downloadClient.DownloadFileCompleted += new AsyncCompletedEventHandler(downloadClient_DownloadFileCompleted);   
            downloadClient.DownloadFileAsync(new Uri(fileUrl), download_path);      
           void downloadClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
            {
                double bytesIn = double.Parse(e.BytesReceived.ToString());
                double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
                double percentage = bytesIn / totalBytes * 100;
                int progress_value = int.Parse(Math.Truncate(percentage).ToString());
                progress_value = (progress_value < 5) ? 5 : (progress_value > 95) ? 95 : progress_value;          
                lblDownloadProgress.Content = string.Format("DOWNLOADING - {0}%", progress_value.ToString());
            }
            void downloadClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
            {
                string item = (string)e.UserState;
                if (e.Error != null )
                {

                    lblDownloadProgress.Content = "Unable to download.Try again.....";
                    lblDownloadProgress.Foreground = Brushes.Red;
                }
                else if (e.Cancelled)
                {
                    //Do Nothing
                }
                else
                {
                    lblDownloadProgress.Content ="DOWNLOADED..";
                }
            }

现在我可以并行运行这两件事吗?就像在下载文件时运行后台工作人员一样? 如果文件下载首先完成,请等待后台工作人员完成 如果后台工作人员先完成,请等待下载完成
在两个操作完成后启用控件并始终保持 UI 响应

【问题讨论】:

  • 当您将任务与更现代的 API(如 HttpClient)结合使用时,这些担忧就会消失。

标签: c# multithreading backgroundworker


【解决方案1】:

您可以并行运行 2 个后台工作人员,但如果您需要检查其中一个工作人员的状态,您可以检查后台工作人员是否忙(正在工作或已完成)。

private void syncWorker_DoWork(object sender, DoWorkEventArgs e)
    {
     while( downloadClient.IsBusy)
            {

             Sleep(5000);

             //waiting downloadClient  worker to complete
            }

             //continue the work
}

【讨论】:

  • 睡眠会让我的 UI 冻结吗?我可以在这里用 async -await 做任何事情吗?
  • 不,因为睡眠是在 dowork 线程中,不会影响 GUI。您甚至可以在 dowork 线程中启动另一个简单的线程进行下载,并在与 MyThread.Join() 相同的 dowork 方法中等待它;(我会这样做,因为您的案例背景很好,但最后有很多代码)跨度>
【解决方案2】:

看看这个,看看你能做些什么。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Threading;

namespace download_demo
{
    class Program
    {


        static void Main(string[] args)
        {   
            BackgroundWorker MyWorker = new BackgroundWorker();
           MyWorker.DoWork += MyWorker_DoWork;
           MyWorker.RunWorkerCompleted +=MyWorker_RunWorkerCompleted;
           MyWorker.RunWorkerAsync();
           Console.ReadKey();
        }

        private static void MyWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Console.WriteLine("both job completed");
        }

        private static void MyWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            Thread download = new Thread(DownloadJob);
            download.Start();
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(20);
                Console.WriteLine("doing some job while downloading ");

            }
            Console.WriteLine("waiting the end of download......... ");
            download.Join();

        }

        private static void DownloadJob(object path)
        {
           /// process download the path
           ///simulate 20 seconde of download
           for(int i = 0;i<100;i++)
           {
               Thread.Sleep(50);
               Console.WriteLine("downloaded :" + i + " Ko");
           }
        }

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-23
    • 1970-01-01
    • 2015-09-13
    • 2021-04-06
    • 1970-01-01
    • 2014-09-06
    • 1970-01-01
    相关资源
    最近更新 更多